r15105 - gnucash/branches/gda-dev - 1) Use getter/setter functions to transfer from objects <-> db

Phil Longstaff plongstaff at cvs.gnucash.org
Fri Nov 10 14:58:17 EST 2006


Author: plongstaff
Date: 2006-11-10 14:58:15 -0500 (Fri, 10 Nov 2006)
New Revision: 15105
Trac: http://svn.gnucash.org/trac/changeset/15105

Modified:
   gnucash/branches/gda-dev/GDA_STATUS
   gnucash/branches/gda-dev/src/backend/gda/gnc-account-gda.c
   gnucash/branches/gda-dev/src/backend/gda/gnc-backend-gda.c
   gnucash/branches/gda-dev/src/backend/gda/gnc-backend-gda.h
   gnucash/branches/gda-dev/src/backend/gda/gnc-commodity-gda.c
   gnucash/branches/gda-dev/src/backend/gda/gnc-price-gda.c
Log:
1) Use getter/setter functions to transfer from objects <-> db
2) Create tables if they don't exist
3) Add handlers for each table column type



Modified: gnucash/branches/gda-dev/GDA_STATUS
===================================================================
--- gnucash/branches/gda-dev/GDA_STATUS	2006-11-09 21:53:51 UTC (rev 15104)
+++ gnucash/branches/gda-dev/GDA_STATUS	2006-11-10 19:58:15 UTC (rev 15105)
@@ -2,7 +2,8 @@
 
 Building:
 - I am currently building with libgda 1.99.1 installed in /opt/libgda-1.99.1.
-This location is hard wired into src/backend/gda/Makefile.am as LIBGDA_DIR
+Configure.in will use pkg-config to set up the include and lib information.
+This cannot be overridden (yet) by any switch on the ./configure command.
 
 Execution:
 - A basic GDA backend framework now exists.  This framework accepts URLs of
@@ -10,30 +11,38 @@
 a dataset configured in ~/.libgda/config.  USERNAME and PASSWORD are not
 required but can be specified.
 
-- The backend assumes that the database already exists and tables are set up
-according to src/backend/gda/ddl/gnucash.ddl.  Note that
-src/backend/gda/ddl/business.ddl has not been tried yet, so there are no
-guarantees that any database will accept it.
+- The backend assumes that the database already exists.  Tables will be
+created if they don't exist.  The ddl files in src/backend/gda/ddl are not
+up to date.  Note that src/backend/gda/ddl/business.ddl has not been tried
+yet, so there are no guarantees that any database will accept it.
 
-- The backend will save commodities and load them on startup.  However, they
-will not have the correct GUIDs.
+- The backend will save commodities and load them on startup.
 
 - The backend will save accounts and load them on startup.  Any information
-in slots is not saved or loaded.  Also, because of the commodity GUID issue
-above, accounts will not have the correct commodity.
+in slots is not saved or loaded.
 
+Functional Issues:
+- In the price editor dialog, if you press Add, the dialog commits a price
+with a NULL guid which is rejected by the db.
+
+- Account information in slots is not saved or restored
+
+- If you create a new account, the commodity with that account will be saved
+to the db.  If you create a new price, the commodity with that price will not
+be saved to the db if it doesn't already exist in the db.
+
+GDA backend implementation issues:
+- Should use GdaDataHandler for converting values -> SQL and getting values
+back from the db.  Need to reassess this if using GdaQuery.
+
 TODO:
 
-- Create DB tables if they don't exist
-- gnc_numeric numerator/denominator are gint64, not int
 - Better representation for gnc_numeric - doesn't compare well
-- Map object->tables
 - queries
 - SQLite if just a "file"
-- Fix commodity handling
-- dates should be "date" not stored as string
 - slots
 - lots
 - transactions/splits
 - sched transactions
 - check for memory leaks
+- add --with-libgda= configure option

Modified: gnucash/branches/gda-dev/src/backend/gda/gnc-account-gda.c
===================================================================
--- gnucash/branches/gda-dev/src/backend/gda/gnc-account-gda.c	2006-11-09 21:53:51 UTC (rev 15104)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-account-gda.c	2006-11-10 19:58:15 UTC (rev 15105)
@@ -41,51 +41,95 @@
 
 static QofLogModule log_module = GNC_MOD_BACKEND;
 
+#define TABLE_NAME "accounts"
+
+static gpointer get_commodity( gpointer pObject );
+static void set_commodity( gpointer pObject, const gpointer pValue );
+static gpointer get_parent( gpointer pObject );
+static void set_parent( gpointer pObject, const gpointer pValue );
+
+static col_cvt_t col_table[] =
+{
+	{ "guid",			CT_GUID,	  0, COL_NNUL|COL_PKEY,
+			(GNC_GDA_FN_GETTER)qof_entity_get_guid,
+			(GNC_GDA_FN_SETTER)xaccAccountSetGUID },
+	{ "name",			CT_STRING,	 50, COL_NNUL,
+			NULL, NULL, ACCOUNT_NAME_ },
+	{ "account_type",	CT_INT,		  0, COL_NNUL,
+			(GNC_GDA_FN_GETTER)xaccAccountGetType,
+			(GNC_GDA_FN_SETTER)xaccAccountSetType },
+	{ "commodity_guid",	CT_GUID,	  0, COL_NNUL,
+			get_commodity, set_commodity },
+	{ "parent_guid",	CT_GUID,	  0, 0,	get_parent, set_parent },
+	{ "code",			CT_STRING,	100, 0,
+			NULL, NULL, ACCOUNT_CODE_ },
+	{ "description",	CT_STRING,	500, 0,
+			NULL, NULL, ACCOUNT_DESCRIPTION_ },
+	{ NULL }
+};
+
 /* ================================================================= */
-static Account*
-load_account( GncGdaBackend* be, GdaDataModel* pModel, int row )
+static gpointer
+get_commodity( gpointer pObject )
 {
-	Account* pAccount;
-	GUID guid;
-	const gchar* name = NULL;
-	gint type = ACCT_TYPE_INVALID;
-	GUID commodity_guid;
-	GUID parent_guid;
-	Account* pParent = NULL;
-	const gchar* code = NULL;
-	const gchar* description = NULL;
+	Account* pAccount = (Account*)pObject;
+
+	return (gpointer)qof_instance_get_guid(
+						(QofInstance*)xaccAccountGetCommodity( pAccount ) );
+}
+
+static void 
+set_commodity( gpointer pObject, const gpointer pValue )
+{
+	Account* pAccount = (Account*)pObject;
+	QofBook* pBook = qof_instance_get_book( (QofInstance*)pAccount );
 	gnc_commodity* pCommodity;
-	QofBook* pBook = be->primary_book;
+	GUID* guid = (GUID*)pValue;
 
-	col_cvt_t col_conversion_table[] =
-	{
-		{ "guid",				CT_GUID,	&guid },
-		{ "name",				CT_STRING,	&name },
-		{ "account_type_id",	CT_INT,		&type },
-		{ "commodity_guid",		CT_GUID,	&commodity_guid },
-		{ "parent_guid",		CT_GUID,	&parent_guid },
-		{ "code",				CT_STRING,	&code },
-		{ "description",		CT_STRING,	&description },
-		{ NULL }
-	};
+	pCommodity = gnc_commodity_find_commodity_by_guid( guid, pBook );
+	xaccAccountSetCommodity( pAccount, pCommodity );
+}
 
-	gnc_gda_load_object( be, pModel, col_conversion_table, row );
+static gpointer
+get_parent( gpointer pObject )
+{
+	const Account* pAccount = (const Account*)pObject;
+	Account* pParent = xaccAccountGetParentAccount( pAccount );
+	const GUID* parent_guid;
 
-	pCommodity = gnc_commodity_find_commodity_by_guid( &commodity_guid, pBook );
-	pParent = xaccAccountLookup( &parent_guid, pBook );
+	if( pParent == NULL ) {
+		parent_guid = NULL;
+	} else {
+		parent_guid = qof_instance_get_guid( (QofInstance*)pParent );
+	}
 
-	pAccount = xaccMallocAccount( pBook );
-	xaccAccountSetGUID( pAccount, &guid );
-	xaccAccountSetName( pAccount, name );
-	xaccAccountSetType( pAccount, type );
-	xaccAccountSetCode( pAccount, code );
-	xaccAccountSetDescription( pAccount, description );
-	xaccAccountSetCommodity( pAccount, pCommodity );
+	return (gpointer)parent_guid;
+}
 
-	if( pParent != NULL ) {
-		xaccAccountInsertSubAccount( pParent, pAccount );
+static void 
+set_parent( gpointer pObject, const gpointer pValue )
+{
+	Account* pAccount = (Account*)pObject;
+	QofBook* pBook = qof_instance_get_book( (QofInstance*)pAccount );
+	GUID* guid = (GUID*)pValue;
+	Account* pParent;
+	
+	if( guid != NULL ) {
+		pParent = xaccAccountLookup( guid, pBook );
+		if( pParent != NULL ) {
+			xaccAccountInsertSubAccount( pParent, pAccount );
+		}
 	}
+}
 
+static Account*
+load_account( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+	Account* pAccount;
+
+	pAccount = xaccMallocAccount( be->primary_book );
+	gnc_gda_load_object( pModel, row, GNC_ID_ACCOUNT, pAccount, col_table );
+
 	return pAccount;
 }
 
@@ -93,13 +137,15 @@
 load_accounts( GncGdaBackend* be )
 {
 	GError* error = NULL;
-
+	gchar* buf;
 	GdaQuery* query;
 	GdaObject* ret;
 	QofBook* pBook = be->primary_book;
 	gnc_commodity_table* pTable = gnc_commodity_table_get_table( pBook );
 
+	buf = g_strdup_printf( "SELECT * FROM %s", TABLE_NAME );
 	query = gda_query_new_from_sql( be->pDict, "SELECT * FROM accounts", &error );
+	g_free( buf );
 	if( query == NULL ) {
 		printf( "SQL error: %s\n", error->message );
 		return;
@@ -133,45 +179,30 @@
 
 /* ================================================================= */
 static void
+create_account_tables( GncGdaBackend* be )
+{
+	GdaDictTable* table;
+	GError* error = NULL;
+	GdaDictDatabase* db;
+	
+	db = gda_dict_get_database( be->pDict );
+	table = gda_dict_database_get_table_by_name( db, TABLE_NAME );
+	if( !GDA_IS_DICT_TABLE(table) ) {
+		gnc_gda_create_table( be->pConnection, TABLE_NAME, col_table, &error );
+	}
+}
+
+/* ================================================================= */
+static void
 commit_account( GncGdaBackend* be, QofInstance* inst )
 {
 	Account* pAcc = (Account*)inst;
-	Account* pParent = xaccAccountGetParentAccount( pAcc );
-	gnc_commodity* c;
-	const GUID* guid = xaccAccountGetGUID( pAcc );
-	gchar guid_buf[GUID_ENCODING_LENGTH+1];
-	const GUID* commodity_guid;
-	const GUID* parent_guid;
-	const gchar* name = xaccAccountGetName(pAcc);
-	const gchar* code = xaccAccountGetCode(pAcc);
-	const gchar* description = xaccAccountGetDescription(pAcc);
-	GNCAccountType type = xaccAccountGetType(pAcc);
 
-	col_cvt_t col_conversion_table[] =
-	{
-		{ "guid",				CT_GUID,	&guid },
-		{ "name",				CT_STRING,	&name },
-		{ "account_type_id",	CT_INT,		&type },
-		{ "commodity_guid",		CT_GUID,	&commodity_guid },
-		{ "parent_guid",		CT_GUID,	&parent_guid },
-		{ "code",				CT_STRING,	&code },
-		{ "description",		CT_STRING,	&description },
-		{ NULL }
-	};
-
-	c = xaccAccountGetCommodity(pAcc);
-	commodity_guid = qof_instance_get_guid( (QofInstance*)c );
-
-	if( pParent == NULL ) {
-		parent_guid = NULL;
-	} else {
-		parent_guid = xaccAccountGetGUID( pParent );
-	}
-
 	(void)gnc_gda_do_db_operation( be,
 							(inst->do_free ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
-							"accounts",
-							col_conversion_table );
+							TABLE_NAME,
+							GNC_ID_ACCOUNT, pAcc,
+							col_table );
 }
 
 /* ================================================================= */
@@ -183,7 +214,8 @@
 		GNC_GDA_BACKEND_VERSION,
 		GNC_ID_ACCOUNT,
 		commit_account,				/* commit */
-		load_accounts				/* initial_load */
+		load_accounts,				/* initial_load */
+		create_account_tables		/* create_tables */
 	};
 
 	qof_object_register_backend( GNC_ID_ACCOUNT, GNC_GDA_BACKEND, &be_data );

Modified: gnucash/branches/gda-dev/src/backend/gda/gnc-backend-gda.c
===================================================================
--- gnucash/branches/gda-dev/src/backend/gda/gnc-backend-gda.c	2006-11-09 21:53:51 UTC (rev 15104)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-backend-gda.c	2006-11-10 19:58:15 UTC (rev 15105)
@@ -67,6 +67,9 @@
 
 static const gchar* convert_search_obj( QofIdType objType );
 static void gnc_gda_init_object_handlers( void );
+static void add_table_column( GdaServerProvider* server, GdaConnection* cnn,
+			xmlNodePtr array_data, const gchar* arg, const gchar* dbms_type,
+			gint size, gint flags );
 
 /* callback structure */
 typedef struct {
@@ -77,59 +80,362 @@
 
 static QofLogModule log_module = GNC_MOD_BACKEND;
 
+typedef void (*GNC_GDA_LOAD_FN)( GdaDataModel* pModel, gint row,
+								QofSetterFunc setter, gpointer pObject,
+								const col_cvt_t* table );
+typedef gchar* (*GNC_GDA_RENDER_FN)( QofIdTypeConst obj_name, gpointer pObject,
+				const col_cvt_t* table_row, gboolean include_name );
+typedef void (*GNC_GDA_CREATE_COL_FN)( GdaServerProvider* server,
+						GdaConnection* cnn, xmlNodePtr array_data,
+						const col_cvt_t* table_row );
+
+typedef struct {
+	GNC_GDA_LOAD_FN			load_fn;
+	GNC_GDA_RENDER_FN		render_fn;
+	GNC_GDA_CREATE_COL_FN	create_col_fn;
+} col_type_handler_t;
+
+
 /* ================================================================= */
-void
-gnc_gda_load_object( GncGdaBackend* be, GdaDataModel* pModel,
-					const col_cvt_t* table, int row )
+/* ----------------------------------------------------------------- */
+static void
+load_string( GdaDataModel* pModel, gint row,
+			QofSetterFunc setter, gpointer pObject,
+			const col_cvt_t* table )
 {
-	int col;
 	const GValue* val;
 	const gchar* s;
-	const GdaTimestamp* pTimestamp;
-	gchar *buf;
-	gint num;
-	gint denom;
-	GUID* guid;
 
-	for( col = 0; table[col].col_name != NULL; col++ ) {
-		if( table[col].col_type != CT_NUMERIC ) {
-			val = gda_data_model_get_value_at_col_name( pModel, table[col].col_name, row );
-		}
-		
-		switch( table[col].col_type ) {
-			case CT_STRING:
-				*(const gchar**)table[col].pData = g_value_get_string( val );
-				break;
+	val = gda_data_model_get_value_at_col_name( pModel, table->col_name, row );
+	if( gda_value_is_null( val ) ) {
+		s = NULL;
+	} else {
+		s = g_value_get_string( val );
+	}
+	(*setter)( pObject, (const gpointer)s );
+}
 
-			case CT_INT:
-				*(gint*)table[col].pData = g_value_get_int( val );
-				break;
+static gchar*
+render_string( QofIdTypeConst obj_name, gpointer pObject,
+				const col_cvt_t* table_row, gboolean include_name )
+{
+	gchar* buf;
+	const gchar* col_name = "";
+	const gchar* equals = "";
+	QofAccessFunc getter;
+	const gchar* s;
 
-			case CT_GUID:
-				s = g_value_get_string( val );
-				string_to_guid( s, (GUID*)table[col].pData );
-				break;
+	if( include_name ) {
+		col_name = table_row->col_name;
+		equals = "=";
+	}
+	if( table_row->param_name != NULL ) {
+		getter = qof_class_get_parameter_getter( obj_name,
+												table_row->param_name );
+		s = (*getter)( pObject, NULL );
+	} else {
+		s = (*table_row->getter)( pObject );
+	}
+	if( s ) {
+		buf = g_strdup_printf( "%s%s'%s'", col_name, equals, s );
+	} else {
+		buf = g_strdup_printf( "%s%sNULL", col_name, equals );
+	}
+
+	return buf;
+}
+
+static void
+create_string_col( GdaServerProvider* server, GdaConnection* cnn,
+			xmlNodePtr array_data, const col_cvt_t* table_row )
+{
+	const gchar* dbms_type;
+
+	dbms_type = gda_server_provider_get_default_dbms_type( server,
+														cnn, G_TYPE_STRING );
+	add_table_column( server, cnn, array_data, table_row->col_name,
+					dbms_type, table_row->size, table_row->flags );
+}
+
+static col_type_handler_t string_handler
+	= { load_string, render_string, create_string_col };
+/* ----------------------------------------------------------------- */
+
+static void
+load_int( GdaDataModel* pModel, gint row,
+			QofSetterFunc setter, gpointer pObject,
+			const col_cvt_t* table )
+{
+	const GValue* val;
+	gint int_value;
+
+	val = gda_data_model_get_value_at_col_name( pModel, table->col_name, row );
+	int_value = g_value_get_int( val );
+	(*setter)( pObject, (gpointer)int_value );
+}
+
+static gchar*
+render_int( QofIdTypeConst obj_name, gpointer pObject,
+				const col_cvt_t* table_row, gboolean include_name )
+{
+	gchar* buf;
+	const gchar* col_name = "";
+	const gchar* equals = "";
+	gint int_value;
+
+	if( include_name ) {
+		col_name = table_row->col_name;
+		equals = "=";
+	}
+	int_value = (gint)(*table_row->getter)( pObject );
+	buf = g_strdup_printf( "%s%s%d", col_name, equals, int_value );
+
+	return buf;
+}
+
+static void
+create_int_col( GdaServerProvider* server, GdaConnection* cnn,
+			xmlNodePtr array_data, const col_cvt_t* table_row )
+{
+	const gchar* dbms_type;
+
+	dbms_type = gda_server_provider_get_default_dbms_type( server,
+														cnn, G_TYPE_INT );
+	add_table_column( server, cnn, array_data, table_row->col_name,
+					dbms_type, table_row->size, table_row->flags );
+}
+
+static col_type_handler_t int_handler =
+		{ load_int, render_int, create_int_col };
+/* ----------------------------------------------------------------- */
+
+static void
+load_guid( GdaDataModel* pModel, gint row,
+			QofSetterFunc setter, gpointer pObject,
+			const col_cvt_t* table )
+{
+	const GValue* val;
+	GUID guid;
+	const GUID* pGuid;
+
+	val = gda_data_model_get_value_at_col_name( pModel, table->col_name, row );
+	if( gda_value_is_null( val ) ) {
+		pGuid = NULL;
+	} else {
+		string_to_guid( g_value_get_string( val ), &guid );
+		pGuid = &guid;
+	}
+	(*setter)( pObject, (gpointer)pGuid );
+}
+
+static gchar*
+render_guid( QofIdTypeConst obj_name, gpointer pObject,
+				const col_cvt_t* table_row, gboolean include_name )
+{
+	gchar* buf;
+	const gchar* col_name = "";
+	const gchar* equals = "";
+	const GUID* guid;
+	gchar guid_buf[GUID_ENCODING_LENGTH+1];
+	const gchar* s;
+
+	if( include_name ) {
+		col_name = table_row->col_name;
+		equals = "=";
+	}
+	if( table_row->getter != NULL ) {
+		guid = (*table_row->getter)( pObject );
+	} else {
+		guid = NULL;
+	}
+	if( guid != NULL ) {
+		(void)guid_to_string_buff( guid, guid_buf );
+		buf = g_strdup_printf( "%s%s'%s'", col_name, equals, guid_buf );
+	} else {
+		buf = g_strdup_printf( "%s%sNULL", col_name, equals );
+	}
+
+	return buf;
+}
+
+static void
+create_guid_col( GdaServerProvider* server, GdaConnection* cnn,
+			xmlNodePtr array_data, const col_cvt_t* table_row )
+{
+	add_table_column( server, cnn, array_data, table_row->col_name,
+					"char", GUID_ENCODING_LENGTH, table_row->flags );
+}
+
+static col_type_handler_t guid_handler =
+		{ load_guid, render_guid, create_guid_col };
+/* ----------------------------------------------------------------- */
+static void
+load_date( GdaDataModel* pModel, gint row,
+			QofSetterFunc setter, gpointer pObject,
+			const col_cvt_t* table )
+{
+	const GValue* val;
+	Timespec ts;
+
+	val = gda_data_model_get_value_at_col_name( pModel, table->col_name, row );
+	ts = gnc_iso8601_to_timespec_gmt( gda_value_stringify( val ) );
+	(*setter)( pObject, &ts );
+}
+
+static gchar*
+render_date( QofIdTypeConst obj_name, gpointer pObject,
+				const col_cvt_t* table_row, gboolean include_name )
+{
+	gchar* buf;
+	const gchar* col_name = "";
+	const gchar* equals = "";
+	gchar iso8601_buf[33];
+	gchar date_buf[33];
+
+	if( include_name ) {
+		col_name = table_row->col_name;
+		equals = "=";
+	}
+	(void)gnc_timespec_to_iso8601_buff(
+								*(Timespec*)(*table_row->getter)( pObject ),
+								iso8601_buf );
+	strncpy( date_buf, iso8601_buf, 4+1+2+1+2 );
+	buf = g_strdup_printf( "%s%s'%s'", col_name, equals, date_buf );
+
+	return buf;
+}
+
+static void
+create_date_col( GdaServerProvider* server, GdaConnection* cnn,
+			xmlNodePtr array_data, const col_cvt_t* table_row )
+{
+	const gchar* dbms_type;
+
+	dbms_type = gda_server_provider_get_default_dbms_type( server,
+														cnn, G_TYPE_DATE );
+	add_table_column( server, cnn, array_data, table_row->col_name,
+					dbms_type, table_row->size, table_row->flags );
+}
+
+static col_type_handler_t date_handler =
+		{ load_date, render_date, create_date_col };
+/* ----------------------------------------------------------------- */
+static void
+load_numeric( GdaDataModel* pModel, gint row,
+			QofSetterFunc setter, gpointer pObject,
+			const col_cvt_t* table )
+{
+	const GValue* val;
+	gchar* buf;
+	gint64 num, denom;
+	gnc_numeric n;
+
+	buf = g_strdup_printf( "%s_num", table->col_name );
+	val = gda_data_model_get_value_at_col_name( pModel, buf, row );
+	g_free( buf );
+	num = g_value_get_int64( val );
+	buf = g_strdup_printf( "%s_denom", table->col_name );
+	val = gda_data_model_get_value_at_col_name( pModel, buf, row );
+	g_free( buf );
+	denom = g_value_get_int64( val );
+	n = gnc_numeric_create( num, denom );
+	(*setter)( pObject, &n );
+}
+
+static gchar*
+render_numeric( QofIdTypeConst obj_name, gpointer pObject,
+				const col_cvt_t* table_row, gboolean include_name )
+{
+	gchar* buf;
+	gnc_numeric v;
+
+	v = *(gnc_numeric*)(*table_row->getter) (pObject );
+	if( !include_name ) {
+		buf = g_strdup_printf( "%lld, %lld",
+								gnc_numeric_num( v ), gnc_numeric_denom( v ) );
+	} else {
+		buf = g_strdup_printf( "%s_num=%lld, %s_denom=%lld",
+						table_row->col_name, gnc_numeric_num( v ),
+						table_row->col_name, gnc_numeric_denom( v ) );
+	}
+
+	return buf;
+}
+
+static void
+create_numeric_col( GdaServerProvider* server, GdaConnection* cnn,
+			xmlNodePtr array_data, const col_cvt_t* table_row )
+{
+	const gchar* dbms_type;
+	gchar* buf;
+
+	dbms_type = gda_server_provider_get_default_dbms_type( server, cnn,
+															G_TYPE_INT64 );
+	buf = g_strdup_printf( "%s_num", table_row->col_name );
+	add_table_column( server, cnn, array_data, buf, dbms_type,
+						table_row->size, table_row->flags );
+	g_free( buf );
+	buf = g_strdup_printf( "%s_denom", table_row->col_name );
+	add_table_column( server, cnn, array_data, buf, dbms_type,
+						table_row->size, table_row->flags );
+	g_free( buf );
+}
+
+static col_type_handler_t numeric_handler =
+		{ load_numeric, render_numeric, create_numeric_col };
+/* ================================================================= */
+
+static col_type_handler_t*
+get_handler( int col_type )
+{
+	col_type_handler_t* pHandler;
+
+	switch( col_type ) {
+		case CT_STRING:
+			pHandler = &string_handler;
+			break;
+
+		case CT_INT:
+			pHandler = &int_handler;
+			break;
+
+		case CT_GUID:
+			pHandler = &guid_handler;
+			break;
 				
-			case CT_DATE:
-				s = g_value_get_string( val );
-				*(Timespec*)table[col].pData = gnc_iso8601_to_timespec_gmt( s );
-				break;
+		case CT_DATE:
+			pHandler = &date_handler;
+			break;
 
-			case CT_NUMERIC:
-				buf = g_strdup_printf( "%s_num", table[col].col_name );
-				val = gda_data_model_get_value_at_col_name( pModel, buf, row );
-				g_free( buf );
-				num = g_value_get_int( val );
-				buf = g_strdup_printf( "%s_denom", table[col].col_name );
-				val = gda_data_model_get_value_at_col_name( pModel, buf, row );
-				g_free( buf );
-				denom = g_value_get_int( val );
-				*(gnc_numeric*)table[col].pData = gnc_numeric_create( num, denom );
-				break;
+		case CT_NUMERIC:
+			pHandler = &numeric_handler;
+			break;
 
-			default:	/* undefined col */
-				g_assert( FALSE );
+		default:	/* undefined col type */
+			g_assert( FALSE );
+	}
+
+	return pHandler;
+}
+
+void
+gnc_gda_load_object( GdaDataModel* pModel, gint row,
+					QofIdTypeConst obj_name, gpointer pObject,
+					const col_cvt_t* table )
+{
+	int col;
+	QofSetterFunc setter;
+	col_type_handler_t* pHandler;
+
+	for( col = 0; table[col].col_name != NULL; col++ ) {
+		if( table[col].param_name != NULL ) {
+			setter = qof_class_get_parameter_setter( obj_name,
+													table[col].param_name );
+		} else {
+			setter = table[col].setter;
 		}
+		pHandler = get_handler( table[col].col_type );
+		pHandler->load_fn( pModel, row, setter, pObject, &table[col] );
 	}
 }
 
@@ -187,79 +493,27 @@
 }
 /* ================================================================= */
 static gchar*
-render_col_value( GncGdaBackend* be, const col_cvt_t* table_row, gboolean include_name )
+render_col_value( QofIdTypeConst obj_name, gpointer pObject,
+				const col_cvt_t* table_row, gboolean include_name )
 {
 	gchar* buf;
-	gchar guid_buf[GUID_ENCODING_LENGTH+1];
-	gchar iso8601_buf[33];
-	gchar date_buf[33];
-	gnc_numeric v;
-	gnc_commodity* pCommodity;
-	const GUID* guid;
-	const gchar* col_name = "";
-	const gchar* equals = "";
+	col_type_handler_t* pHandler;
+	pHandler = get_handler( table_row->col_type );
 
-	// CT_NUMERIC are special because they are actually stored as 2 cols
-	if( include_name && table_row->col_type != CT_NUMERIC ) {
-		col_name = table_row->col_name;
-		equals = "=";
-	}
-	switch( table_row->col_type ) {
-		case CT_STRING:
-			if( *(char**)table_row->pData != NULL ) {
-				buf = g_strdup_printf( "%s%s'%s'",
-								col_name, equals,
-								*(gchar**)table_row->pData );
-			} else {
-				buf = g_strdup_printf( "%s%sNULL", col_name, equals );
-			}
-			break;
-
-		case CT_GUID:
-			(void)guid_to_string_buff( *(GUID**)table_row->pData, guid_buf );
-			buf = g_strdup_printf( "%s%s'%s'", col_name, equals, guid_buf );
-			break;
-
-		case CT_DATE:
-			(void)gnc_timespec_to_iso8601_buff( *(Timespec*)table_row->pData,
-												iso8601_buf );
-			strncpy( date_buf, iso8601_buf, 4+1+2+1+2 );
-			buf = g_strdup_printf( "%s%s'%s'", col_name, equals, date_buf );
-			break;
-
-		case CT_INT:
-			buf = g_strdup_printf( "%s%s%d",
-									col_name, equals,
-									*(gint*)table_row->pData );
-			break;
-
-		case CT_NUMERIC:
-			v = *(gnc_numeric*)table_row->pData;
-			if( !include_name ) {
-				buf = g_strdup_printf( "%lld, %lld",
-								gnc_numeric_num( v ), gnc_numeric_denom( v ) );
-			} else {
-				buf = g_strdup_printf( "%s_num=%lld, %s_denom=%lld",
-						table_row->col_name, gnc_numeric_num( v ),
-						table_row->col_name, gnc_numeric_denom( v ) );
-			}
-			break;
-
-		default:
-			g_assert( FALSE );
-	}
-
+	buf = pHandler->render_fn( obj_name, pObject, table_row, include_name );
 	return buf;
 }
 
 static gboolean
-object_exists_in_db( GncGdaBackend* be, const gchar* table_name, const col_cvt_t* table )
+object_exists_in_db( GncGdaBackend* be, const gchar* table_name,
+					QofIdTypeConst obj_name, gpointer pObject,
+					const col_cvt_t* table )
 {
 	gchar* sql;
 	int count;
 	gchar* key_value;
 
-	key_value = render_col_value( be, table, TRUE );
+	key_value = render_col_value( obj_name, pObject, table, TRUE );
 
 	sql = g_strdup_printf( "SELECT * FROM %s WHERE %s;",
 							table_name, key_value );
@@ -278,18 +532,19 @@
 gnc_gda_do_db_operation( GncGdaBackend* be,
 						E_DB_OPERATION op,
 						const gchar* table_name,
+						QofIdTypeConst obj_name, gpointer pObject,
 						const col_cvt_t* table )
 {
 	GdaQuery* pQuery;
 
 	if( op == OP_DB_ADD_OR_UPDATE ) {
-		if( object_exists_in_db( be, table_name, table ) ) {
-			pQuery = gnc_gda_build_update_query( be, table_name, table );
+		if( object_exists_in_db( be, table_name, obj_name, pObject, table ) ) {
+			pQuery = gnc_gda_build_update_query( be, table_name, obj_name, pObject, table );
 		} else {
-			pQuery = gnc_gda_build_insert_query( be, table_name, table );
+			pQuery = gnc_gda_build_insert_query( be, table_name, obj_name, pObject, table );
 		}
 	} else if( op == OP_DB_DELETE ) {
-		pQuery = gnc_gda_build_delete_query( be, table_name, table );
+		pQuery = gnc_gda_build_delete_query( be, table_name, obj_name, pObject, table );
 	} else {
 		g_assert( FALSE );
 	}
@@ -306,6 +561,7 @@
 GdaQuery*
 gnc_gda_build_insert_query( GncGdaBackend* be,
 							const gchar* table_name,
+							QofIdTypeConst obj_name, gpointer pObject,
 							const col_cvt_t* table )
 {
 	char sql[1000];
@@ -318,7 +574,7 @@
 
 	for( col = 0; table[col].col_name != NULL; col++ ) {
 		if( col != 0 ) strcat( sql, "," );
-		col_value = render_col_value( be, &table[col], FALSE );
+		col_value = render_col_value( obj_name, pObject, &table[col], FALSE );
 		strcat( sql, col_value );
 		g_free( col_value );
 	}
@@ -335,6 +591,7 @@
 GdaQuery*
 gnc_gda_build_update_query( GncGdaBackend* be,
 							const gchar* table_name,
+							QofIdTypeConst obj_name, gpointer pObject,
 							const col_cvt_t* table )
 {
 	char sql[1000];
@@ -348,14 +605,14 @@
 	for( col = 1; table[col].col_name != NULL; col++ ) {
 		if( col != 1 ) strcat( sql, "," );
 
-		col_value = render_col_value( be, &table[col], TRUE );
+		col_value = render_col_value( obj_name, pObject, &table[col], TRUE );
 		strcat( sql, col_value );
 		g_free( col_value );
 	}
 
 	strcat( sql, " WHERE " );
 
-	col_value = render_col_value( be, &table[0], TRUE );
+	col_value = render_col_value( obj_name, pObject, &table[0], TRUE );
 	strcat( sql, col_value );
 	g_free( col_value );
 	strcat( sql, ";" );
@@ -370,6 +627,7 @@
 GdaQuery*
 gnc_gda_build_delete_query( GncGdaBackend* be,
 							const gchar* table_name,
+							QofIdTypeConst obj_name, gpointer pObject,
 							const col_cvt_t* table )
 {
 	gchar* sql;
@@ -377,7 +635,7 @@
 	GdaQuery* query;
 	gchar* col_value;
 
-	col_value = render_col_value( be, &table[0], TRUE );
+	col_value = render_col_value( obj_name, pObject, &table[0], TRUE );
 	sql = g_strdup_printf( "DELETE FROM %s WHERE %s;", table_name, col_value );
 	g_free( col_value );
 
@@ -390,8 +648,146 @@
 }
 
 /* ================================================================= */
+static void
+add_table_column( GdaServerProvider* server, GdaConnection* cnn,
+			xmlNodePtr array_data, const gchar* arg, const gchar* dbms_type,
+			gint size, gint flags )
+{
+	xmlNodePtr array_row, array_value;
+	gchar* buf;
 
+	array_row = xmlNewChild( array_data, NULL, "gda_array_row", NULL );
+	array_value = xmlNewChild( array_row, NULL, "gda_array_value", arg );
+	xmlSetProp( array_value, "colid", "COLUMN_NAME" );
+	array_value = xmlNewChild( array_row, NULL, "gda_array_value", dbms_type );
+	xmlSetProp( array_value, "colid", "COLUMN_TYPE" );
+	if( size != 0 ) {
+		buf = g_strdup_printf( "%d", size );
+		array_value = xmlNewChild( array_row, NULL, "gda_array_value", buf );
+		xmlSetProp( array_value, "colid", "COLUMN_SIZE" );
+		g_free( buf );
+	}
+	if( (flags & COL_PKEY) != 0 ) {
+		array_value = xmlNewChild( array_row, NULL, "gda_array_value", "TRUE" );
+		xmlSetProp( array_value, "colid", "COLUMN_PKEY" );
+	}
+	if( (flags & COL_NNUL) != 0 ) {
+		array_value = xmlNewChild( array_row, NULL, "gda_array_value", "TRUE" );
+		xmlSetProp( array_value, "colid", "COLUMN_NNUL" );
+	}
+	if( (flags & COL_AUTOINC) != 0 ) {
+		array_value = xmlNewChild( array_row, NULL, "gda_array_value", "TRUE" );
+		xmlSetProp( array_value, "colid", "COLUMN_AUTOINC" );
+	}
+	if( (flags & COL_UNIQUE) != 0 ) {
+		array_value = xmlNewChild( array_row, NULL, "gda_array_value", "TRUE" );
+		xmlSetProp( array_value, "colid", "COLUMN_UNIQUE" );
+	}
+}
+
+gboolean
+gnc_gda_create_table( GdaConnection* cnn, const gchar* table_name,
+					col_cvt_t* col_table, GError** error )
+{
+	GdaServerOperation *op;
+	GdaServerProvider *server;
+	
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnn), FALSE);
+	g_return_val_if_fail (gda_connection_is_opened (cnn), FALSE);
+	
+	server = gda_connection_get_provider_obj(cnn);
+	
+	op = gda_server_provider_create_operation (server, cnn, 
+						   GDA_SERVER_OPERATION_CREATE_TABLE, NULL, error);
+	if (GDA_IS_SERVER_OPERATION (op)) {
+		gint col;
+		GType type;
+		xmlDocPtr parameters;
+		xmlNodePtr root;
+		xmlNodePtr table, op_data, array_data, array_row, array_value;
+		
+		if (table_name == NULL) {
+			g_message("Table name is NULL!");      
+			g_set_error (error, GDA_GENERAL_ERROR, GDA_GENERAL_OBJECT_NAME_ERROR, 
+				    "Couldn't create table with a NULL string");
+			return FALSE;    
+		}
+		
+	
+		/* Initation of the xmlDoc */
+		parameters = xmlNewDoc ("1.0");
+		
+		root = xmlNewDocNode (parameters, NULL, "serv_op_data", NULL);
+		xmlDocSetRootElement (parameters, root);
+		table = xmlNewChild (root, NULL, "op_data", table_name);
+		xmlSetProp (table, "path", "/TABLE_DEF_P/TABLE_NAME");
+
+		op_data = xmlNewChild (root, NULL, "op_data", NULL);
+		xmlSetProp (op_data, "path", "/FIELDS_A");
+		array_data = xmlNewChild (op_data, NULL, "gda_array_data", NULL);
+			
+		type = 0;
+		
+		for( col = 0; col_table[col].col_name != NULL; col++ ) {
+			gchar* buf;
+			gchar *dbms_type = NULL;
+			const gchar *arg;
+			gint size;
+			gint flags;
+			col_type_handler_t* pHandler;
+
+			pHandler = get_handler( col_table[col].col_type );
+
+			pHandler->create_col_fn( server, cnn, array_data, &col_table[col] );
+		}
+		
+		if (!gda_server_operation_load_data_from_xml (op, root, error)) {
+			/* error */
+			g_set_error (error, GDA_GENERAL_ERROR, GDA_GENERAL_OPERATION_ERROR, 
+				     "The XML operation doesn't exist or could't be loaded");
+			g_object_unref (op);
+			xmlFreeDoc(parameters);
+			return FALSE;
+		}
+		else {
+			if (gda_server_provider_perform_operation (server, cnn, op, error)) {
+				/* error */
+				g_set_error(error, GDA_GENERAL_ERROR, GDA_GENERAL_OPERATION_ERROR, 
+					    "The Server couldn't perform the CREATE TABLE operation!");
+				g_object_unref (op);
+				xmlFreeDoc(parameters);
+				return FALSE;
+			}
+		}
+		
+		g_object_unref (op);
+		xmlFreeDoc(parameters);
+	}
+	else {
+		g_set_error(error, GDA_GENERAL_ERROR, GDA_GENERAL_OBJECT_NAME_ERROR, 
+			    "The Server doesn't support the CREATE TABLE operation!");
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/* ================================================================= */
+
 static void
+create_tables_cb( const gchar* type, gpointer data_p, gpointer be_data_p )
+{
+	GncGdaDataType_t* pData = data_p;
+	gda_backend* be_data = be_data_p;
+
+	g_return_if_fail( type != NULL && pData != NULL && be_data != NULL );
+	g_return_if_fail( pData->version == GNC_GDA_BACKEND_VERSION );
+
+	if( pData->create_tables != NULL ) {
+		(pData->create_tables)( be_data->be );
+	}
+}
+
+static void
 gnc_gda_session_begin(QofBackend *be_start, QofSession *session, 
                    const gchar *book_id,
                    gboolean ignore_lock, gboolean create_if_nonexistent)
@@ -439,13 +835,26 @@
 		return;
 	}
 
+	// Set up the dictionary
 	be->pDict = gda_dict_new();
 	gda_dict_set_connection( be->pDict, be->pConnection );
 	gda_dict_update_dbms_meta_data( be->pDict, 0, NULL, &error );
 	if( error != NULL ) {
-		printf( "SQL error: %s\n", error->message );
+		printf( "gda_dict_update_dbms_meta_data() error: %s\n", error->message );
 	}
 
+	// Call all object backends to create any required tables
+	be_data.ok = FALSE;
+	be_data.be = be;
+	be_data.inst = NULL;
+	qof_object_foreach_backend( GNC_GDA_BACKEND, create_tables_cb, &be_data );
+
+	// Update the dictionary because new tables may exist
+	gda_dict_update_dbms_meta_data( be->pDict, 0, NULL, &error );
+	if( error != NULL ) {
+		printf( "gda_dict_update_dbms_meta_data() error: %s\n", error->message );
+	}
+
     LEAVE (" ");
 }
 

Modified: gnucash/branches/gda-dev/src/backend/gda/gnc-backend-gda.h
===================================================================
--- gnucash/branches/gda-dev/src/backend/gda/gnc-backend-gda.h	2006-11-09 21:53:51 UTC (rev 15104)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-backend-gda.h	2006-11-10 19:58:15 UTC (rev 15105)
@@ -63,16 +63,28 @@
 
   void		(*commit)( GncGdaBackend* pBackend, QofInstance* inst );
   void		(*initial_load)( GncGdaBackend* pBackend );
+  void		(*create_tables)( GncGdaBackend* pBackend );
 } GncGdaDataType_t;
 
 // This is now a static inside the module
 //QofBackend * libgncmod_backend_gda_LTX_gnc_backend_new(void);
 
 // Type for conversion of db row to object.
+typedef gpointer (*GNC_GDA_FN_GETTER)( gpointer pObject );
+typedef void (*GNC_GDA_FN_SETTER)( gpointer pObject, gpointer pValue );
+
 typedef struct {
 	const gchar* col_name;
 	enum { CT_STRING, CT_GUID, CT_INT, CT_DATE, CT_NUMERIC } col_type;
-	gpointer pData;
+	gint size;
+#define COL_PKEY	0x01
+#define COL_NNUL	0x02
+#define COL_UNIQUE	0x04
+#define COL_AUTOINC	0x08
+	gint flags;
+	GNC_GDA_FN_GETTER getter;
+	GNC_GDA_FN_SETTER setter;
+	const char* param_name;
 } col_cvt_t;
 
 typedef enum { OP_DB_ADD_OR_UPDATE, OP_DB_DELETE } E_DB_OPERATION;
@@ -80,21 +92,33 @@
 gboolean gnc_gda_do_db_operation( GncGdaBackend* pBackend,
 									E_DB_OPERATION op,
 									const gchar* table_name,
+									QofIdTypeConst obj_name,
+									gpointer pObject,
 									const col_cvt_t* table );
 GdaQuery* gnc_gda_build_insert_query( GncGdaBackend* pBackend,
 									const gchar* table_name,
+									QofIdTypeConst obj_name,
+									gpointer pObject,
 									const col_cvt_t* table );
 GdaQuery* gnc_gda_build_update_query( GncGdaBackend* pBackend,
 									const gchar* table_name,
+									QofIdTypeConst obj_name,
+									gpointer pObject,
 									const col_cvt_t* table );
 GdaQuery* gnc_gda_build_delete_query( GncGdaBackend* pBackend,
 									const gchar* table_name,
+									QofIdTypeConst obj_name,
+									gpointer pObject,
 									const col_cvt_t* table );
 GdaObject* gnc_gda_execute_query( GncGdaBackend* pBackend, GdaQuery* pQuery );
 GdaObject* gnc_gda_execute_sql( GncGdaBackend* pBackend, const gchar* sql );
 int gnc_gda_execute_select_get_count( GncGdaBackend* pBackend, const gchar* sql );
-void gnc_gda_load_object( GncGdaBackend* be, GdaDataModel* pModel,
-							const col_cvt_t* table, int row );
+void gnc_gda_load_object( GdaDataModel* pModel, int row,
+						QofIdTypeConst obj_name, gpointer pObject,
+						const col_cvt_t* table );
+gboolean gnc_gda_create_table( GdaConnection* pConnection,
+						const gchar* table_name, col_cvt_t* col_table,
+						GError** error );
 
 G_MODULE_EXPORT const gchar *
 g_module_check_init(GModule *module);

Modified: gnucash/branches/gda-dev/src/backend/gda/gnc-commodity-gda.c
===================================================================
--- gnucash/branches/gda-dev/src/backend/gda/gnc-commodity-gda.c	2006-11-09 21:53:51 UTC (rev 15104)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-commodity-gda.c	2006-11-10 19:58:15 UTC (rev 15105)
@@ -43,26 +43,63 @@
 
 static QofLogModule log_module = GNC_MOD_BACKEND;
 
-/*
--- Commodities table - stores currencies and stocks/mutual funds
-CREATE TABLE commodities (
-	guid char(32) NOT NULL,
+static gpointer get_quote_source_name( gpointer pObject );
+static void set_quote_source_name( gpointer pObject, const gpointer pValue );
 
-	namespace text NOT NULL,
-	mnemonic text NOT NULL,
+#define TABLE_NAME "commodities"
 
-	fullname text,
-	cusip text,
-	fraction int,
-	use_quote_source boolean,
-	quote_source text,
-	quote_tz text,
+static col_cvt_t col_table[] = {
+	{ "guid",			CT_GUID,	  0, COL_NNUL|COL_PKEY,
+			(GNC_GDA_FN_GETTER)qof_entity_get_guid,
+			(GNC_GDA_FN_SETTER)qof_entity_set_guid },
+	{ "namespace",		CT_STRING,	 40, COL_NNUL,
+			(GNC_GDA_FN_GETTER)gnc_commodity_get_namespace,
+			(GNC_GDA_FN_SETTER)gnc_commodity_set_namespace },
+	{ "mnemonic",		CT_STRING,	 40, COL_NNUL,
+			(GNC_GDA_FN_GETTER)gnc_commodity_get_mnemonic,
+			(GNC_GDA_FN_SETTER)gnc_commodity_set_mnemonic },
+	{ "fullname",		CT_STRING,	100, COL_NNUL,
+			(GNC_GDA_FN_GETTER)gnc_commodity_get_fullname,
+			(GNC_GDA_FN_SETTER)gnc_commodity_set_fullname },
+	{ "cusip",			CT_STRING,	 50, COL_NNUL,
+			(GNC_GDA_FN_GETTER)gnc_commodity_get_cusip,
+			(GNC_GDA_FN_SETTER)gnc_commodity_set_cusip },
+	{ "fraction",		CT_INT,		  0, COL_NNUL,
+			(GNC_GDA_FN_GETTER)gnc_commodity_get_fraction,
+			(GNC_GDA_FN_SETTER)gnc_commodity_set_fraction },
+	{ "quote_flag",		CT_INT,		  0, COL_NNUL,
+			(GNC_GDA_FN_GETTER)gnc_commodity_get_quote_flag,
+			(GNC_GDA_FN_SETTER)gnc_commodity_set_quote_flag },
+	{ "quote_source",	CT_STRING,	 50, 0,
+			get_quote_source_name, set_quote_source_name },
+	{ "quote_tz",		CT_STRING,	 50, 0,
+			(GNC_GDA_FN_GETTER)gnc_commodity_get_quote_tz,
+			(GNC_GDA_FN_SETTER)gnc_commodity_set_quote_tz },
+	{ NULL }
+};
 
-	PRIMARY KEY(guid)
-);
-*/
 /* ================================================================= */
 
+static gpointer
+get_quote_source_name( gpointer pObject )
+{
+	gnc_commodity* pCommodity = (gnc_commodity*)pObject;
+
+	return (gpointer)gnc_quote_source_get_internal_name(
+							gnc_commodity_get_quote_source(pCommodity));
+}
+
+static void 
+set_quote_source_name( gpointer pObject, const gpointer pValue )
+{
+	gnc_commodity* pCommodity = (gnc_commodity*)pObject;
+	const gchar* quote_source_name = (const gchar*)pValue;
+	gnc_quote_source* quote_source;
+
+	quote_source = gnc_quote_source_lookup_by_internal( quote_source_name );
+	gnc_commodity_set_quote_source( pCommodity, quote_source );
+}
+
 static gnc_commodity*
 load_commodity( GncGdaBackend* be, GdaDataModel* pModel, int row )
 {
@@ -70,41 +107,11 @@
 	int col;
 	const GValue* val;
 	gnc_commodity* pCommodity;
-	GUID guid;
-	const gchar* namespace = NULL;
-	const gchar* mnemonic = NULL;
-	const gchar* fullname = NULL;
-	const gchar* cusip = NULL;
-	int fraction = 1;
-	gboolean quote_flag = FALSE;
-	const gchar* quote_source_name = NULL;
-	gnc_quote_source* quote_source = NULL;
-	const gchar* quote_tz = NULL;
-	const gchar* s;
 
-	col_cvt_t col_conversion[] = {
-		{ "guid",				CT_GUID,	&guid },
-		{ "namespace",			CT_STRING,	&namespace },
-		{ "mnemonic",			CT_STRING,	&mnemonic },
-		{ "fullname",			CT_STRING,	&fullname },
-		{ "cusip",				CT_STRING,	&cusip },
-		{ "fraction",			CT_INT,		&fraction },
-		{ "use_quote_source",	CT_INT,		&quote_flag },
-		{ "quote_source",		CT_STRING,	&quote_source_name },
-		{ "quote_tz",			CT_STRING,	&quote_tz },
-		{ NULL }
-	};
+	pCommodity = gnc_commodity_new( pBook, NULL, NULL, NULL, NULL, 100 );
 
-	gnc_gda_load_object( be, pModel, col_conversion, row );
+	gnc_gda_load_object( pModel, row, GNC_ID_COMMODITY, pCommodity, col_table );
 
-	pCommodity = gnc_commodity_new( pBook, fullname, namespace, mnemonic,
-									cusip, fraction );
-	gnc_commodity_set_quote_flag( pCommodity, quote_flag );
-	quote_source = gnc_quote_source_lookup_by_internal( quote_source_name );
-	gnc_commodity_set_quote_source( pCommodity, quote_source );
-	gnc_commodity_set_quote_tz( pCommodity, quote_tz );
-	qof_entity_set_guid( (QofEntity*)pCommodity, &guid );
-
 	return pCommodity;
 }
 
@@ -112,15 +119,15 @@
 load_commodities( GncGdaBackend* be )
 {
 	GError* error = NULL;
-
+	gchar* buf;
 	GdaQuery* query;
 	GdaObject* ret;
 	QofBook* pBook = be->primary_book;
 	gnc_commodity_table* pTable = gnc_commodity_table_get_table( pBook );
 
-	query = gda_query_new_from_sql( be->pDict,
-									"SELECT * FROM commodities",
-									&error );
+	buf = g_strdup_printf( "SELECT * FROM %s", TABLE_NAME );
+	query = gda_query_new_from_sql( be->pDict, buf, &error );
+	g_free( buf );
 	if( query == NULL ) {
 		printf( "SQL error: %s\n", error->message );
 		return;
@@ -154,37 +161,30 @@
 }
 /* ================================================================= */
 static void
+create_commodities_tables( GncGdaBackend* be )
+{
+	GdaDictTable* table;
+	GError* error = NULL;
+	GdaDictDatabase* db;
+	
+	db = gda_dict_get_database( be->pDict );
+	table = gda_dict_database_get_table_by_name( db, TABLE_NAME );
+	if( !GDA_IS_DICT_TABLE(table) ) {
+		gnc_gda_create_table( be->pConnection, TABLE_NAME, col_table, &error );
+	}
+}
+
+/* ================================================================= */
+static void
 commit_commodity( GncGdaBackend* be, QofInstance* inst )
 {
 	gnc_commodity* pCommodity = (gnc_commodity*)inst;
-	const gchar* mnemonic = gnc_commodity_get_mnemonic(pCommodity);
-	const gchar* namespace = gnc_commodity_get_namespace(pCommodity);
-	const gchar* fullname = gnc_commodity_get_fullname(pCommodity);
-	const gchar* cusip = gnc_commodity_get_cusip(pCommodity);
-	int fraction = gnc_commodity_get_fraction(pCommodity);
-	const gchar* quote_source = gnc_quote_source_get_user_name(gnc_commodity_get_quote_source(pCommodity));
-	const gchar* quote_tz = gnc_commodity_get_quote_tz(pCommodity);
-	const GUID* guid = qof_instance_get_guid( inst );
-	gboolean quote_flag = gnc_commodity_get_quote_flag(pCommodity);
-	GdaQuery* pQuery;
 
-	col_cvt_t col_conversion_table[] = {
-		{ "guid",				CT_GUID,	&guid },
-		{ "namespace",			CT_STRING,	&namespace },
-		{ "mnemonic",			CT_STRING,	&mnemonic },
-		{ "fullname",			CT_STRING,	&fullname },
-		{ "cusip",				CT_STRING,	&cusip },
-		{ "fraction",			CT_INT,		&fraction },
-		{ "use_quote_source",	CT_INT,		&quote_flag },
-		{ "quote_source",		CT_STRING,	&quote_source },
-		{ "quote_tz",			CT_STRING,	&quote_tz },
-		{ NULL }
-	};
-
 	(void)gnc_gda_do_db_operation( be,
 						(inst->do_free ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
-						"commodities",
-						col_conversion_table );
+						TABLE_NAME,
+						GNC_ID_COMMODITY, pCommodity,
+						col_table );
 }
 
 /* ================================================================= */
@@ -196,7 +196,8 @@
 		GNC_GDA_BACKEND_VERSION,
 		GNC_ID_COMMODITY,
 		commit_commodity,			/* commit */
-		load_commodities			/* initial_load */
+		load_commodities,			/* initial_load */
+		create_commodities_tables	/* create_tables */
 	};
 
 	qof_object_register_backend( GNC_ID_COMMODITY, GNC_GDA_BACKEND, &be_data );

Modified: gnucash/branches/gda-dev/src/backend/gda/gnc-price-gda.c
===================================================================
--- gnucash/branches/gda-dev/src/backend/gda/gnc-price-gda.c	2006-11-09 21:53:51 UTC (rev 15104)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-price-gda.c	2006-11-10 19:58:15 UTC (rev 15105)
@@ -40,51 +40,123 @@
 
 static QofLogModule log_module = GNC_MOD_BACKEND;
 
+#define TABLE_NAME "prices"
+
+static gpointer get_value( gpointer pObject );
+static void set_value( gpointer pObject, const gpointer pValue );
+static gpointer get_date( gpointer pObject );
+static void set_date( gpointer pObject, const gpointer pValue );
+static gpointer get_currency( gpointer pObject );
+static void set_currency( gpointer pObject, const gpointer pValue );
+static gpointer get_commodity( gpointer pObject );
+static void set_commodity( gpointer pObject, const gpointer pValue );
+
+static col_cvt_t col_table[] =
+{
+	{ "guid",			CT_GUID,	0, COL_NNUL|COL_PKEY,
+			(GNC_GDA_FN_GETTER)qof_entity_get_guid,
+			(GNC_GDA_FN_SETTER)qof_entity_set_guid },
+	{ "commodity_guid",	CT_GUID,	0, COL_NNUL, get_commodity, set_commodity },
+	{ "currency_guid",	CT_GUID,	0, COL_NNUL, get_currency, set_currency },
+	{ "date",			CT_DATE,	0, COL_NNUL, get_date, set_date },
+	{ "source",			CT_STRING,	50, 0,
+			NULL, NULL, PRICE_SOURCE },
+	{ "type",			CT_STRING,	50, 0,
+			NULL, NULL, PRICE_TYPE },
+	{ "value",			CT_NUMERIC,	COL_NNUL, 0, get_value, set_value },
+	{ NULL }
+};
+
 /* ================================================================= */
-static GNCPrice*
-load_price( GncGdaBackend* be, GdaDataModel* pModel, int row )
+static gpointer
+get_value( gpointer pObject )
 {
-	QofBook* pBook = be->primary_book;
-	GNCPrice* pPrice;
-	GUID guid;
-	GUID commodity_guid;
-	GUID currency_guid;
-	Timespec date;
-	const gchar* source = NULL;
-	const gchar* type = NULL;
-	gnc_numeric value;
+	GNCPrice* pPrice = (GNCPrice*)pObject;
+	static gnc_numeric v;
 
-	Account* pParent = NULL;
-	const gchar* code = NULL;
-	const gchar* description = NULL;
-	gnc_commodity* pCommodity;
+	v = gnc_price_get_value( pPrice );
+	return &v;
+}
+
+static void
+set_value( gpointer pObject, const gpointer pValue )
+{
+	GNCPrice* pPrice = (GNCPrice*)pObject;
+	const gnc_numeric* pNumeric = (const gnc_numeric*)pValue;
+
+	gnc_price_set_value( pPrice, *pNumeric );
+}
+
+static gpointer
+get_date( gpointer pObject )
+{
+	GNCPrice* pPrice = (GNCPrice*)pObject;
+	static Timespec t;
+
+	t = gnc_price_get_time( pPrice );
+	return &t;
+}
+
+static void
+set_date( gpointer pObject, const gpointer pValue )
+{
+	GNCPrice* pPrice = (GNCPrice*)pObject;
+	const Timespec* pTimespec = (const Timespec*)pValue;
+
+	gnc_price_set_time( pPrice, *pTimespec );
+}
+
+static gpointer
+get_currency( gpointer pObject )
+{
+	GNCPrice* pPrice = (GNCPrice*)pObject;
+
+	return (gpointer)qof_instance_get_guid(
+							(QofInstance*)gnc_price_get_currency( pPrice ) );
+}
+
+static void 
+set_currency( gpointer pObject, const gpointer pValue )
+{
+	GNCPrice* pPrice = (GNCPrice*)pObject;
+	QofBook* pBook = qof_instance_get_book( (QofInstance*)pPrice );
 	gnc_commodity* pCurrency;
+	GUID* guid = (GUID*)pValue;
 
-	col_cvt_t col_conversion_table[] =
-	{
-		{ "guid",			CT_GUID,	&guid },
-		{ "commodity_guid",	CT_GUID,	&commodity_guid },
-		{ "currency_guid",	CT_GUID,	&currency_guid },
-		{ "time",			CT_DATE,	&date },
-		{ "source",			CT_STRING,	&source },
-		{ "type",			CT_STRING,	&type },
-		{ "value",			CT_NUMERIC,	&value },
-		{ NULL }
-	};
+	pCurrency = gnc_commodity_find_commodity_by_guid( guid, pBook );
+	gnc_price_set_currency( pPrice, pCurrency );
+}
 
-	gnc_gda_load_object( be, pModel, col_conversion_table, row );
+static gpointer
+get_commodity( gpointer pObject )
+{
+	GNCPrice* pPrice = (GNCPrice*)pObject;
 
-	pCommodity = gnc_commodity_find_commodity_by_guid( &commodity_guid, pBook );
-	pCurrency = gnc_commodity_find_commodity_by_guid( &currency_guid, pBook );
+	return (gpointer)qof_instance_get_guid(
+						(QofInstance*)gnc_price_get_commodity( pPrice ) );
+}
 
-	pPrice = gnc_price_create( pBook );
+static void 
+set_commodity( gpointer pObject, const gpointer pValue )
+{
+	GNCPrice* pPrice = (GNCPrice*)pObject;
+	QofBook* pBook = qof_instance_get_book( (QofInstance*)pPrice );
+	gnc_commodity* pCommodity;
+	GUID* guid = (GUID*)pValue;
+
+	pCommodity = gnc_commodity_find_commodity_by_guid( guid, pBook );
 	gnc_price_set_commodity( pPrice, pCommodity );
-	gnc_price_set_currency( pPrice, pCurrency );
-	gnc_price_set_time( pPrice, date );
-	gnc_price_set_source( pPrice, source );
-	gnc_price_set_type( pPrice, type );
-	gnc_price_set_value( pPrice, value );
+}
 
+static GNCPrice*
+load_price( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+	GNCPrice* pPrice;
+
+	pPrice = gnc_price_create( be->primary_book );
+
+	gnc_gda_load_object( pModel, row, GNC_ID_PRICE, pPrice, col_table );
+
 	return pPrice;
 }
 
@@ -92,13 +164,15 @@
 load_prices( GncGdaBackend* be )
 {
 	GError* error = NULL;
-
+	gchar* buf;
 	GdaQuery* query;
 	GdaObject* ret;
 	QofBook* pBook = be->primary_book;
 	GNCPriceDB* pPriceDB = gnc_book_get_pricedb( pBook );
 
-	query = gda_query_new_from_sql( be->pDict, "SELECT * FROM prices", &error );
+	buf = g_strdup_printf( "SELECT * FROM %s", TABLE_NAME );
+	query = gda_query_new_from_sql( be->pDict, buf, &error );
+	g_free( buf );
 	if( query == NULL ) {
 		printf( "SQL error: %s\n", error->message );
 		return;
@@ -127,6 +201,21 @@
 }
 
 /* ================================================================= */
+static void
+create_prices_tables( GncGdaBackend* be )
+{
+	GdaDictTable* table;
+	GError* error = NULL;
+	GdaDictDatabase* db;
+	
+	db = gda_dict_get_database( be->pDict );
+	table = gda_dict_database_get_table_by_name( db, TABLE_NAME );
+	if( !GDA_IS_DICT_TABLE(table) ) {
+		gnc_gda_create_table( be->pConnection, TABLE_NAME, col_table, &error );
+	}
+}
+
+/* ================================================================= */
 static gboolean
 price_exists_in_db( GncGdaBackend* be, const gchar* guid )
 {
@@ -147,40 +236,12 @@
 commit_price( GncGdaBackend* be, QofInstance* inst )
 {
 	GNCPrice* pPrice = (GNCPrice*)inst;
-	gnc_commodity* c;
-	const GUID* guid = qof_instance_get_guid( inst );
-	const GUID* commodity_guid;
-	const GUID* currency_guid;
-	Timespec date = gnc_price_get_time( pPrice );
-	const gchar* source = gnc_price_get_source( pPrice );
-	const gchar* type = gnc_price_get_type( pPrice );
-	gnc_numeric value = gnc_price_get_value( pPrice );
-	GdaQuery* query;
-	gchar guid_buf[GUID_ENCODING_LENGTH+1];
 
-	col_cvt_t col_conversion_table[] =
-	{
-		{ "guid",			CT_GUID,	&guid },
-		{ "commodity_guid",	CT_GUID,	&commodity_guid },
-		{ "currency_guid",	CT_GUID,	&currency_guid },
-		{ "time",			CT_DATE,	&date },
-		{ "source",			CT_STRING,	&source },
-		{ "type",			CT_STRING,	&type },
-		{ "value",			CT_NUMERIC,	&value },
-		{ NULL }
-	};
-
-	guid_to_string_buff( guid, guid_buf );
-
-	c = gnc_price_get_commodity( pPrice );
-	commodity_guid = qof_instance_get_guid( (QofInstance*)c );
-	c = gnc_price_get_currency( pPrice );
-	currency_guid = qof_instance_get_guid( (QofInstance*)c );
-
 	(void)gnc_gda_do_db_operation( be,
 							(inst->do_free ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
-							"prices",
-							col_conversion_table );
+							TABLE_NAME,
+							GNC_ID_PRICE, pPrice,
+							col_table );
 }
 
 /* ================================================================= */
@@ -192,7 +253,8 @@
 		GNC_GDA_BACKEND_VERSION,
 		GNC_ID_PRICE,
 		commit_price,			/* commit */
-		load_prices				/* initial_load */
+		load_prices,			/* initial_load */
+		create_prices_tables	/* create tables */
 	};
 
 	qof_object_register_backend( GNC_ID_PRICE, GNC_GDA_BACKEND, &be_data );



More information about the gnucash-changes mailing list