r15100 - gnucash/branches/gda-dev - 1) Fix commodity handling

Phil Longstaff plongstaff at cvs.gnucash.org
Wed Nov 8 21:05:08 EST 2006


Author: plongstaff
Date: 2006-11-08 21:05:06 -0500 (Wed, 08 Nov 2006)
New Revision: 15100
Trac: http://svn.gnucash.org/trac/changeset/15100

Modified:
   gnucash/branches/gda-dev/GDA_STATUS
   gnucash/branches/gda-dev/src/backend/gda/Makefile.am
   gnucash/branches/gda-dev/src/backend/gda/ddl/prices.ddl
   gnucash/branches/gda-dev/src/backend/gda/gnc-account-gda.c
   gnucash/branches/gda-dev/src/backend/gda/gnc-account-gda.h
   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-budget-gda.c
   gnucash/branches/gda-dev/src/backend/gda/gnc-budget-gda.h
   gnucash/branches/gda-dev/src/backend/gda/gnc-commodity-gda.c
   gnucash/branches/gda-dev/src/backend/gda/gnc-commodity-gda.h
   gnucash/branches/gda-dev/src/backend/gda/gnc-price-gda.c
   gnucash/branches/gda-dev/src/backend/gda/gnc-price-gda.h
   gnucash/branches/gda-dev/src/backend/gda/gnc-transaction-gda.c
   gnucash/branches/gda-dev/src/backend/gda/gnc-transaction-gda.h
   gnucash/branches/gda-dev/src/backend/gda/gncmod-backend-gda.c
Log:
1) Fix commodity handling
2) Save/load prices
3) Start using column -> variable mapping and common functions



Modified: gnucash/branches/gda-dev/GDA_STATUS
===================================================================
--- gnucash/branches/gda-dev/GDA_STATUS	2006-11-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/GDA_STATUS	2006-11-09 02:05:06 UTC (rev 15100)
@@ -21,3 +21,19 @@
 - 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.
+
+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

Modified: gnucash/branches/gda-dev/src/backend/gda/Makefile.am
===================================================================
--- gnucash/branches/gda-dev/src/backend/gda/Makefile.am	2006-11-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/src/backend/gda/Makefile.am	2006-11-09 02:05:06 UTC (rev 15100)
@@ -15,7 +15,7 @@
   ${QOF_CFLAGS} \
   ${GLIB_CFLAGS} \
   ${GCONF_CFLAGS} \
-  -I/usr/include/libxml2 -I$(LIBGDA_DIR)
+  -I/usr/include/libxml2 -I$(LIBGDA_DIR)/include/libgda-1.99
 
 libgnc_backend_gda_la_SOURCES = \
   gnc-backend-gda.c \
@@ -43,4 +43,4 @@
 
 libgnc_backend_gda_la_LDFLAGS = -module -avoid-version
 libgnc_backend_gda_la_LIBADD = \
-	-L$(LIBGDA_DIR) -lgda-3 -lgda_handlers-3 -lgda_sql_delimiter-3 -lglib-2.0 -lxslt -lxml2 -lz -lm
+	-L$(LIBGDA_DIR)/lib -lgda-3 -lgda_handlers-3 -lgda_sql_delimiter-3 -lglib-2.0 -lxslt -lxml2 -lz -lm

Modified: gnucash/branches/gda-dev/src/backend/gda/ddl/prices.ddl
===================================================================
--- gnucash/branches/gda-dev/src/backend/gda/ddl/prices.ddl	2006-11-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/src/backend/gda/ddl/prices.ddl	2006-11-09 02:05:06 UTC (rev 15100)
@@ -2,9 +2,9 @@
 	guid char(32) NOT NULL,
 	commodity_guid char(32) NOT NULL,
 	currency_guid char(32) NOT NULL,
-	time date NOT NULL,
-	source text,
-	type text,
+	time varchar(40) NOT NULL,
+	source varchar(40),
+	type varchar(40),
 	value_num int,
 	value_denom int,
 

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-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-account-gda.c	2006-11-09 02:05:06 UTC (rev 15100)
@@ -20,9 +20,6 @@
 \********************************************************************/
 /** @file gnc-account-gda.c
  *  @brief load and save data to SQL 
- *  @author Copyright (c) 2000 Gnumatic Inc.
- *  @author Copyright (c) 2002 Derek Atkins <warlord at MIT.EDU>
- *  @author Copyright (c) 2003 Linas Vepstas <linas at linas.org>
  *  @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
  *
  * This file implements the top-level QofBackend API for saving/
@@ -62,73 +59,41 @@
 
 #include "gnc-account-gda.h"
 
-#ifndef HAVE_STRPTIME
-# include "strptime.h"
-#endif
-
-/* callback structure */
-typedef struct {
-	gboolean ok;
-	GdaConnection* pConnection;
-	QofInstance* inst;
-} gda_backend;
-
 static QofLogModule log_module = GNC_MOD_BACKEND;
 
 /* ================================================================= */
 static Account*
-load_account( QofBook* pBook, GdaDataModel* pModel, int row )
+load_account( GncGdaBackend* be, GdaDataModel* pModel, int row )
 {
-	int numCols = gda_data_model_get_n_columns( pModel );
-	int col;
-	const GValue* val;
 	Account* pAccount;
 	GUID guid;
-	const char* name = NULL;
-	int type = ACCT_TYPE_INVALID;
+	const gchar* name = NULL;
+	gint type = ACCT_TYPE_INVALID;
 	GUID commodity_guid;
 	GUID parent_guid;
 	Account* pParent = NULL;
-	const char* code = NULL;
-	const char* description = NULL;
-	const char* s;
+	const gchar* code = NULL;
+	const gchar* description = NULL;
 	gnc_commodity* pCommodity;
+	QofBook* pBook = be->primary_book;
 
-	for( col = 0; col < numCols; col++ ) {
-		val = gda_data_model_get_value_at( pModel, col, row );
-		
-		switch( col ) {
-			case 0:	/* guid */
-				s = g_value_get_string( val );
-				string_to_guid( s, &guid );
-				break;
-			case 1: /* name */
-				name = g_value_get_string( val );
-				break;
-			case 2: /* type */
-				type = g_value_get_int( val );
-				break;
-			case 3: /* commodity_guid */
-				s = g_value_get_string( val );
-				string_to_guid( s, &commodity_guid );
-				pCommodity = gnc_commodity_find_commodity_by_guid( &commodity_guid, pBook );
-				break;
-			case 4: /* parent_guid */
-				s = g_value_get_string( val );
-				string_to_guid( s, &parent_guid );
-				pParent = xaccAccountLookup( &parent_guid, pBook );
-				break;
-			case 5: /* code */
-				code = g_value_get_string( val );
-				break;
-			case 6: /* description */
-				description = g_value_get_string( val );
-				break;
-			default:	/* too many cols */
-				*(char*)0 = 0;
-		}
-	}
+	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 }
+	};
 
+	gnc_gda_load_object( be, pModel, col_conversion_table, row );
+
+	pCommodity = gnc_commodity_find_commodity_by_guid( &commodity_guid, pBook );
+	pParent = xaccAccountLookup( &parent_guid, pBook );
+
 	pAccount = xaccMallocAccount( pBook );
 	xaccAccountSetGUID( pAccount, &guid );
 	xaccAccountSetName( pAccount, name );
@@ -145,12 +110,13 @@
 }
 
 static void
-load_accounts( GncGdaBackend* be, QofBook* pBook )
+load_accounts( GncGdaBackend* be )
 {
 	GError* error = NULL;
 
 	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 accounts", &error );
@@ -172,7 +138,7 @@
 
 		for( r = 0; r < numRows; r++ ) {
 
-			pAccount = load_account( pBook, pModel, r );
+			pAccount = load_account( be, pModel, r );
 
 			if( pAccount != NULL ) {
 				if( xaccAccountGetParent( pAccount ) == NULL ) {
@@ -186,21 +152,6 @@
 }
 
 /* ================================================================= */
-static gboolean
-account_exists_in_db( GncGdaBackend* be, const char* guid )
-{
-	char cmdbuf[400];
-	int count;
-
-	sprintf( cmdbuf, "SELECT * FROM accounts WHERE guid='%s';", guid );
-	count = gnc_gda_execute_select_get_count( be, cmdbuf );
-	if( count == 0 ) {
-		return FALSE;
-	} else {
-		return TRUE;
-	}
-}
-
 static void
 commit_account( GncGdaBackend* be, QofInstance* inst )
 {
@@ -208,44 +159,39 @@
 	Account* pParent = xaccAccountGetParentAccount( pAcc );
 	gnc_commodity* c;
 	const GUID* guid = xaccAccountGetGUID( pAcc );
-	char guid_buf[GUID_ENCODING_LENGTH+1];
-	char commodity_guid_buf[GUID_ENCODING_LENGTH+1];
+	gchar guid_buf[GUID_ENCODING_LENGTH+1];
+	const GUID* commodity_guid;
 	const GUID* parent_guid;
-	char parent_guid_buf[GUID_ENCODING_LENGTH+1];
-	char cmdbuf[300];
-	const char* name = xaccAccountGetName(pAcc);
-	const char* code = xaccAccountGetCode(pAcc);
-	const char* description = xaccAccountGetDescription(pAcc);
+	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 );
 
-	(void)guid_to_string_buff( guid, guid_buf );
-	(void)guid_to_string_buff( qof_instance_get_guid( (QofInstance*)c ),
-								commodity_guid_buf );
 	if( pParent == NULL ) {
-		parent_guid_buf[0] = '\0';
+		parent_guid = NULL;
 	} else {
 		parent_guid = xaccAccountGetGUID( pParent );
-		(void)guid_to_string_buff( parent_guid, parent_guid_buf );
 	}
 
-	if( inst->do_free ) {
-		sprintf( cmdbuf, "DELETE FROM accounts WHERE guid='%s';", guid_buf );
-		printf( "%s\n", cmdbuf );
-		gnc_gda_execute_sql( be, cmdbuf );
-	} else {
-		if( account_exists_in_db( be, guid_buf ) ) {
-			sprintf( cmdbuf, "UPDATE accounts set name='%s',account_type_id=%d,commodity_guid='%s',parent_guid='%s',code='%s',description='%s' WHERE guid='%s';\n",
-				name, type, commodity_guid_buf, parent_guid_buf, code, description,
-				guid_buf );
-		} else {
-			sprintf( cmdbuf, "INSERT INTO accounts VALUES('%s','%s',%d,'%s','%s','%s','%s');\n",
-				guid_buf,name, type, commodity_guid_buf, parent_guid_buf, code, description );
-		}
-		printf( "%s\n", cmdbuf );
-		gnc_gda_execute_sql( be, cmdbuf );
-	}
+	(void)gnc_gda_do_db_operation( be,
+							(inst->do_free ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+							"accounts",
+							col_conversion_table );
 }
 
 /* ================================================================= */

Modified: gnucash/branches/gda-dev/src/backend/gda/gnc-account-gda.h
===================================================================
--- gnucash/branches/gda-dev/src/backend/gda/gnc-account-gda.h	2006-11-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-account-gda.h	2006-11-09 02:05:06 UTC (rev 15100)
@@ -20,9 +20,6 @@
 \********************************************************************/
 /** @file gnc-account-gda.h
  *  @brief load and save accounts data to SQL via libgda
- *  @author Copyright (c) 2000 Gnumatic Inc.
- *  @author Copyright (c) 2002 Derek Atkins <warlord at MIT.EDU>
- *  @author Copyright (c) 2003 Linas Vepstas <linas at linas.org>
  *  @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
  *
  * This file implements the top-level QofBackend API for saving/

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-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-backend-gda.c	2006-11-09 02:05:06 UTC (rev 15100)
@@ -20,9 +20,6 @@
 \********************************************************************/
 /** @file gnc-backend-gda.c
  *  @brief load and save data to SQL 
- *  @author Copyright (c) 2000 Gnumatic Inc.
- *  @author Copyright (c) 2002 Derek Atkins <warlord at MIT.EDU>
- *  @author Copyright (c) 2003 Linas Vepstas <linas at linas.org>
  *  @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
  *
  * This file implements the top-level QofBackend API for saving/
@@ -69,55 +66,114 @@
 #endif
 
 static const gchar* convert_search_obj( QofIdType objType );
+static void gnc_gda_init_object_handlers( void );
 
 /* callback structure */
 typedef struct {
 	gboolean ok;
 	GncGdaBackend* be;
 	QofInstance* inst;
-	QofBook* book;
 } gda_backend;
 
 static QofLogModule log_module = GNC_MOD_BACKEND;
 
 /* ================================================================= */
 void
-gnc_gda_execute_sql( GncGdaBackend* be, const char* sql )
+gnc_gda_load_object( GncGdaBackend* be, GdaDataModel* pModel,
+					const col_cvt_t* table, int row )
 {
+	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;
+
+			case CT_INT:
+				*(gint*)table[col].pData = g_value_get_int( val );
+				break;
+
+			case CT_GUID:
+				s = g_value_get_string( val );
+				string_to_guid( s, (GUID*)table[col].pData );
+				break;
+				
+			case CT_DATE:
+				s = g_value_get_string( val );
+				*(Timespec*)table[col].pData = gnc_iso8601_to_timespec_gmt( s );
+				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;
+
+			default:	/* undefined col */
+				g_assert( FALSE );
+		}
+	}
+}
+
+/* ================================================================= */
+GdaObject*
+gnc_gda_execute_query( GncGdaBackend* be, GdaQuery* query )
+{
 	GError* error = NULL;
 
-	GdaQuery* query;
 	GdaObject* ret;
 
-	query = gda_query_new_from_sql( be->pDict, sql, &error );
-	if( query == NULL ) {
-		printf( "SQL error: %s\n", error->message );
-		return;
-	}
-	error = NULL;
 	ret = gda_query_execute( query, NULL, FALSE, &error );
 
 	if( error != NULL ) {
 		printf( "SQL error: %s\n", error->message );
 	}
+
+	return ret;
 }
 
-int
-gnc_gda_execute_select_get_count( GncGdaBackend* be, const char* sql )
+GdaObject*
+gnc_gda_execute_sql( GncGdaBackend* be, const gchar* sql )
 {
 	GError* error = NULL;
-	int count = 0;
 
 	GdaQuery* query;
-	GdaObject* ret;
 
 	query = gda_query_new_from_sql( be->pDict, sql, &error );
 	if( query == NULL ) {
 		printf( "SQL error: %s\n", error->message );
-		return 0;
+		return NULL;
 	}
-	error = NULL;
-	ret = gda_query_execute( query, NULL, FALSE, &error );
+	return gnc_gda_execute_query( be, query );
+}
+
+int
+gnc_gda_execute_select_get_count( GncGdaBackend* be, const gchar* sql )
+{
+	GError* error = NULL;
+	int count = 0;
+
+	GdaObject* ret;
+
+	ret = gnc_gda_execute_sql( be, sql );
 	if( GDA_IS_DATA_MODEL(ret) ) {
 		GdaDataModel* pModel = (GdaDataModel*)ret;
 		count = gda_data_model_get_n_rows( pModel );
@@ -130,26 +186,230 @@
 	return count;
 }
 /* ================================================================= */
+static gchar*
+render_col_value( GncGdaBackend* be, 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 = "";
 
+	// 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 );
+	}
+
+	return buf;
+}
+
+static gboolean
+object_exists_in_db( GncGdaBackend* be, const gchar* table_name, const col_cvt_t* table )
+{
+	gchar* sql;
+	int count;
+	gchar* key_value;
+
+	key_value = render_col_value( be, table, TRUE );
+
+	sql = g_strdup_printf( "SELECT * FROM %s WHERE %s;",
+							table_name, key_value );
+	g_free( key_value );
+
+	count = gnc_gda_execute_select_get_count( be, sql );
+	g_free( sql );
+	if( count == 0 ) {
+		return FALSE;
+	} else {
+		return TRUE;
+	}
+}
+
+gboolean
+gnc_gda_do_db_operation( GncGdaBackend* be,
+						E_DB_OPERATION op,
+						const gchar* table_name,
+						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 );
+		} else {
+			pQuery = gnc_gda_build_insert_query( be, table_name, table );
+		}
+	} else if( op == OP_DB_DELETE ) {
+		pQuery = gnc_gda_build_delete_query( be, table_name, table );
+	} else {
+		g_assert( FALSE );
+	}
+	if( pQuery != NULL ) {
+		gnc_gda_execute_query( be, pQuery );
+		g_object_unref( G_OBJECT(pQuery) );
+
+		return TRUE;
+	} else {
+		return FALSE;
+	}
+}
+
+GdaQuery*
+gnc_gda_build_insert_query( GncGdaBackend* be,
+							const gchar* table_name,
+							const col_cvt_t* table )
+{
+	char sql[1000];
+	GError* error = NULL;
+	GdaQuery* query;
+	int col;
+	gchar* col_value;
+
+	sprintf( sql, "INSERT INTO %s VALUES(", table_name );
+
+	for( col = 0; table[col].col_name != NULL; col++ ) {
+		if( col != 0 ) strcat( sql, "," );
+		col_value = render_col_value( be, &table[col], FALSE );
+		strcat( sql, col_value );
+		g_free( col_value );
+	}
+
+	strcat( sql, ");" );
+
+	query = gda_query_new_from_sql( be->pDict, sql, &error );
+	if( query == NULL ) {
+		printf( "SQL error: %s\n", error->message );
+	}
+	return query;
+}
+
+GdaQuery*
+gnc_gda_build_update_query( GncGdaBackend* be,
+							const gchar* table_name,
+							const col_cvt_t* table )
+{
+	char sql[1000];
+	GError* error = NULL;
+	GdaQuery* query;
+	int col;
+	gchar* col_value;
+
+	sprintf( sql, "UPDATE %s SET ", table_name );
+
+	for( col = 1; table[col].col_name != NULL; col++ ) {
+		if( col != 1 ) strcat( sql, "," );
+
+		col_value = render_col_value( be, &table[col], TRUE );
+		strcat( sql, col_value );
+		g_free( col_value );
+	}
+
+	strcat( sql, " WHERE " );
+
+	col_value = render_col_value( be, &table[0], TRUE );
+	strcat( sql, col_value );
+	g_free( col_value );
+	strcat( sql, ";" );
+
+	query = gda_query_new_from_sql( be->pDict, sql, &error );
+	if( query == NULL ) {
+		printf( "SQL error: %s\n", error->message );
+	}
+	return query;
+}
+
+GdaQuery*
+gnc_gda_build_delete_query( GncGdaBackend* be,
+							const gchar* table_name,
+							const col_cvt_t* table )
+{
+	gchar* sql;
+	GError* error = NULL;
+	GdaQuery* query;
+	gchar* col_value;
+
+	col_value = render_col_value( be, &table[0], TRUE );
+	sql = g_strdup_printf( "DELETE FROM %s WHERE %s;", table_name, col_value );
+	g_free( col_value );
+
+	query = gda_query_new_from_sql( be->pDict, sql, &error );
+	g_free( sql );
+	if( query == NULL ) {
+		printf( "SQL error: %s\n", error->message );
+	}
+	return query;
+}
+
+/* ================================================================= */
+
 static void
 gnc_gda_session_begin(QofBackend *be_start, QofSession *session, 
-                   const char *book_id,
+                   const gchar *book_id,
                    gboolean ignore_lock, gboolean create_if_nonexistent)
 {
     GncGdaBackend *be = (GncGdaBackend*) be_start;
 	GError* error = NULL;
 	gda_backend be_data;
-	char book_info[300];
-	char* dsn;
-	char* username;
-	char* password;
+	gchar* book_info;
+	gchar* dsn;
+	gchar* username;
+	gchar* password;
 
     ENTER (" ");
 
 	be->pClient = gda_client_new();
 
 	/* Split book_id into provider and connection string */
-	strcpy( book_info, book_id );
+	book_info = g_strdup( book_id );
 	dsn = strchr( book_info, ':' );
 	*dsn = '\0';
 	dsn += 3;
@@ -171,6 +431,7 @@
 						username, password,
 						0,
 						&error );
+	g_free( book_info );
 
 	if( be->pConnection == NULL ) {
 		printf( "SQL error: %s\n", error->message );
@@ -221,7 +482,7 @@
 /* ================================================================= */
 
 static void
-initial_load_cb( const char* type, gpointer data_p, gpointer be_data_p )
+initial_load_cb( const gchar* type, gpointer data_p, gpointer be_data_p )
 {
 	GncGdaDataType_t* pData = data_p;
 	gda_backend* be_data = be_data_p;
@@ -230,7 +491,7 @@
 	g_return_if_fail( pData->version == GNC_GDA_BACKEND_VERSION );
 
 	if( pData->initial_load != NULL ) {
-		(pData->initial_load)( be_data->be, be_data->book );
+		(pData->initial_load)( be_data->be );
 	}
 }
 
@@ -242,13 +503,15 @@
 
     ENTER (" ");
 
+	g_assert( be->primary_book == NULL );
+	be->primary_book = book;
+
 	/* Load any initial stuff */
 	be->loading = TRUE;
 
 	be_data.ok = FALSE;
 	be_data.be = be;
 	be_data.inst = NULL;
-	be_data.book = book;
 	qof_object_foreach_backend( GNC_GDA_BACKEND, initial_load_cb, &be_data );
 
 	be->loading = FALSE;
@@ -282,7 +545,7 @@
 }
 
 static void
-commit_cb( const char* type, gpointer data_p, gpointer be_data_p )
+commit_cb( const gchar* type, gpointer data_p, gpointer be_data_p )
 {
 	GncGdaDataType_t* pData = data_p;
 	gda_backend* be_data = be_data_p;
@@ -324,7 +587,9 @@
 	qof_object_foreach_backend( GNC_GDA_BACKEND, commit_cb, &be_data );
 
 	if( !be_data.ok ) {
-		*(char*)0 = 0;
+		printf( "gnc_gda_commit_edit(): Unknown object type %s\n",
+				inst->entity.e_type );
+		return;
 	}
 
 	qof_instance_mark_clean( inst );
@@ -340,13 +605,13 @@
 }
 
 static void
-handle_and_term( QofQueryTerm* pTerm, char* sql )
+handle_and_term( QofQueryTerm* pTerm, gchar* sql )
 {
 	GSList* pParamPath = qof_query_term_get_param_path( pTerm );
 	QofQueryPredData* pPredData = qof_query_term_get_pred_data( pTerm );
 	gboolean isInverted = qof_query_term_is_inverted( pTerm );
 	GSList* name;
-	char val[33];
+	gchar val[GUID_ENCODING_LENGTH+1];
 
 	strcat( sql, "(" );
 	if( isInverted ) {
@@ -417,7 +682,7 @@
 		sprintf( val, "%d", pData->val );
 		strcat( sql, val );
 	} else {
-		*(char*)0 = '\0';
+		g_assert( FALSE );
 	}
 
 	strcat( sql, ")" );
@@ -429,7 +694,7 @@
     GncGdaBackend *be = (GncGdaBackend*)pBEnd;
 	GList* pBookList;
 	QofIdType searchObj;
-	char sql[1000];
+	gchar sql[1000];
 
 	pBookList = qof_query_get_books( pQuery );
 	searchObj = qof_query_get_search_for( pQuery );
@@ -467,18 +732,18 @@
 {
     GncGdaBackend *be = (GncGdaBackend*)pBEnd;
 
-	printf( "gda_free_query(): %s\n", (char*)pQuery );
+	printf( "gda_free_query(): %s\n", (gchar*)pQuery );
 }
 
 static void
 gnc_gda_run_query(QofBackend* pBEnd, gpointer pQuery)
 {
     GncGdaBackend *be = (GncGdaBackend*)pBEnd;
-	printf( "gda_run_query(): %s\n", (char*)pQuery );
+	printf( "gda_run_query(): %s\n", (gchar*)pQuery );
 }
 
 /* ================================================================= */
-void
+static void
 gnc_gda_init_object_handlers( void )
 {
 	gnc_gda_init_commodity_handler();

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-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-backend-gda.h	2006-11-09 02:05:06 UTC (rev 15100)
@@ -20,9 +20,6 @@
 \********************************************************************/
 /** @file gnc-backend-gda.h
  *  @brief load and save data to SQL via libgda
- *  @author Copyright (c) 2000 Gnumatic Inc.
- *  @author Copyright (c) 2002 Derek Atkins <warlord at MIT.EDU>
- *  @author Copyright (c) 2003 Linas Vepstas <linas at linas.org>
  *  @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
  *
  * This file implements the top-level QofBackend API for saving/
@@ -62,19 +59,43 @@
 typedef struct
 {
   int		version;	/* backend version number */
-  const char *	type_name;	/* The XML tag for this type */
+  const gchar *	type_name;	/* The XML tag for this type */
 
   void		(*commit)( GncGdaBackend* pBackend, QofInstance* inst );
-  void		(*initial_load)( GncGdaBackend* pBackend, QofBook* pBook );
+  void		(*initial_load)( GncGdaBackend* pBackend );
 } GncGdaDataType_t;
 
 // This is now a static inside the module
 //QofBackend * libgncmod_backend_gda_LTX_gnc_backend_new(void);
 
-void gnc_gda_init_object_handlers( void );
-void gnc_gda_execute_sql( GncGdaBackend* pBackend, const char* sql );
-int gnc_gda_execute_select_get_count( GncGdaBackend* pBackend, const char* sql );
+// Type for conversion of db row to object.
+typedef struct {
+	const gchar* col_name;
+	enum { CT_STRING, CT_GUID, CT_INT, CT_DATE, CT_NUMERIC } col_type;
+	gpointer pData;
+} col_cvt_t;
 
+typedef enum { OP_DB_ADD_OR_UPDATE, OP_DB_DELETE } E_DB_OPERATION;
+
+gboolean gnc_gda_do_db_operation( GncGdaBackend* pBackend,
+									E_DB_OPERATION op,
+									const gchar* table_name,
+									const col_cvt_t* table );
+GdaQuery* gnc_gda_build_insert_query( GncGdaBackend* pBackend,
+									const gchar* table_name,
+									const col_cvt_t* table );
+GdaQuery* gnc_gda_build_update_query( GncGdaBackend* pBackend,
+									const gchar* table_name,
+									const col_cvt_t* table );
+GdaQuery* gnc_gda_build_delete_query( GncGdaBackend* pBackend,
+									const gchar* table_name,
+									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 );
+
 G_MODULE_EXPORT const gchar *
 g_module_check_init(GModule *module);
 

Modified: gnucash/branches/gda-dev/src/backend/gda/gnc-budget-gda.c
===================================================================
--- gnucash/branches/gda-dev/src/backend/gda/gnc-budget-gda.c	2006-11-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-budget-gda.c	2006-11-09 02:05:06 UTC (rev 15100)
@@ -20,9 +20,6 @@
 \********************************************************************/
 /** @file gnc-budget-gda.c
  *  @brief load and save data to SQL 
- *  @author Copyright (c) 2000 Gnumatic Inc.
- *  @author Copyright (c) 2002 Derek Atkins <warlord at MIT.EDU>
- *  @author Copyright (c) 2003 Linas Vepstas <linas at linas.org>
  *  @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
  *
  * This file implements the top-level QofBackend API for saving/

Modified: gnucash/branches/gda-dev/src/backend/gda/gnc-budget-gda.h
===================================================================
--- gnucash/branches/gda-dev/src/backend/gda/gnc-budget-gda.h	2006-11-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-budget-gda.h	2006-11-09 02:05:06 UTC (rev 15100)
@@ -20,9 +20,6 @@
 \********************************************************************/
 /** @file gnc-backend-gda.h
  *  @brief load and save data to SQL via libgda
- *  @author Copyright (c) 2000 Gnumatic Inc.
- *  @author Copyright (c) 2002 Derek Atkins <warlord at MIT.EDU>
- *  @author Copyright (c) 2003 Linas Vepstas <linas at linas.org>
  *  @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
  *
  * This file implements the top-level QofBackend API for saving/

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-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-commodity-gda.c	2006-11-09 02:05:06 UTC (rev 15100)
@@ -67,6 +67,8 @@
 
 static QofLogModule log_module = GNC_MOD_BACKEND;
 
+static void do_db_commodity( GncGdaBackend* be, QofInstance* inst, gboolean force_insert );
+
 /*
 -- Commodities table - stores currencies and stocks/mutual funds
 CREATE TABLE commodities (
@@ -86,80 +88,65 @@
 );
 */
 /* ================================================================= */
+
 static gnc_commodity*
-load_commodity( QofBook* pBook, GdaDataModel* pModel, int row )
+load_commodity( GncGdaBackend* be, GdaDataModel* pModel, int row )
 {
-	int numCols = gda_data_model_get_n_columns( pModel );
+	QofBook* pBook = be->primary_book;
 	int col;
 	const GValue* val;
 	gnc_commodity* pCommodity;
 	GUID guid;
-	const char* namespace = NULL;
-	const char* mnemonic = NULL;
-	const char* fullname = NULL;
-	const char* cusip = NULL;
+	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 char* quote_tz = NULL;
-	const char* s;
+	const gchar* quote_tz = NULL;
+	const gchar* s;
 
-	for( col = 0; col < numCols; col++ ) {
-		val = gda_data_model_get_value_at( pModel, col, row );
-		
-		switch( col ) {
-			case 0:	/* guid */
-				s = g_value_get_string( val );
-				string_to_guid( s, &guid );
-				break;
-			case 1: /* namespace */
-				namespace = g_value_get_string( val );
-				break;
-			case 2: /* mnemonic */
-				mnemonic = g_value_get_string( val );
-				break;
-			case 3: /* fullname */
-				fullname = g_value_get_string( val );
-				break;
-			case 4: /* cusip */
-				cusip = g_value_get_string( val );
-				break;
-			case 5: /* fraction */
-				fraction = g_value_get_int( val );
-				break;
-			case 6: /* use_quote_source */
-				quote_flag = g_value_get_boolean( val );
-				break;
-			case 7: /* quote_source */
-				quote_source = gnc_quote_source_lookup_by_internal( g_value_get_string( val ) );
-				break;
-			case 8: /* quote_tz */
-				quote_tz = g_value_get_string( val );
-				break;
-			default:	/* too many cols */
-				*(char*)0 = 0;
-		}
-	}
+	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, fullname, namespace, mnemonic, cusip, fraction );
-	memcpy( &((QofInstance*)pCommodity)->entity.guid, &guid, sizeof( GUID ) );
+	gnc_gda_load_object( be, pModel, col_conversion, row );
+
+	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;
 }
 
 static void
-load_commodities( GncGdaBackend* be, QofBook* pBook )
+load_commodities( GncGdaBackend* be )
 {
 	GError* error = NULL;
 
 	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 );
+	query = gda_query_new_from_sql( be->pDict,
+									"SELECT * FROM commodities",
+									&error );
 	if( query == NULL ) {
 		printf( "SQL error: %s\n", error->message );
 		return;
@@ -179,66 +166,59 @@
 		for( r = 0; r < numRows; r++ ) {
 			gnc_commodity* c;
 
-			pCommodity = load_commodity( pBook, pModel, r );
+			pCommodity = load_commodity( be, pModel, r );
 
 			if( pCommodity != NULL ) {
-				gnc_commodity_table_insert( pTable, pCommodity );
+				GUID guid;
+
+				guid = *qof_entity_get_guid( (QofEntity*)pCommodity );
+				pCommodity = gnc_commodity_table_insert( pTable, pCommodity );
+				qof_entity_set_guid( (QofEntity*)pCommodity, &guid );
 			}
 		}
 	}
 }
 /* ================================================================= */
-static gboolean
-commodity_exists_in_db( GncGdaBackend* be, const char* guid )
-{
-	char cmdbuf[400];
-	int count;
-
-	sprintf( cmdbuf, "SELECT * FROM commodities WHERE guid='%s';", guid );
-	count = gnc_gda_execute_select_get_count( be, cmdbuf );
-	if( count == 0 ) {
-		return FALSE;
-	} else {
-		return TRUE;
-	}
-}
-
 static void
-commit_commodity( GncGdaBackend* be, QofInstance* inst )
+do_db_commodity( GncGdaBackend* be, QofInstance* inst, gboolean force_insert )
 {
 	gnc_commodity* pCommodity = (gnc_commodity*)inst;
-	const char* mnemonic = gnc_commodity_get_mnemonic(pCommodity);
-	const char* namespace = gnc_commodity_get_namespace(pCommodity);
-	const char* fullname = gnc_commodity_get_fullname(pCommodity);
-	const char* cusip = gnc_commodity_get_cusip(pCommodity);
+	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 char* quote_source = gnc_quote_source_get_user_name(gnc_commodity_get_quote_source(pCommodity));
-	const char* quote_tz = gnc_commodity_get_quote_tz(pCommodity);
-	char guid[GUID_ENCODING_LENGTH+1];
-	char cmdbuf[1000];
+	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;
 
-	guid_to_string_buff( qof_instance_get_guid( inst ), guid );
+	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 }
+	};
 
-	if( inst->do_free ) {
-		sprintf( cmdbuf, "DELETE FROM commodities WHERE guid='%s';\n", guid );
-		printf( "%s\n", cmdbuf );
-		gnc_gda_execute_sql( be, cmdbuf );
-	} else {
-		if( commodity_exists_in_db( be, guid ) ) {
-			sprintf( cmdbuf,
-				"UPDATE commodities set namespace='%s',mnemonic='%s',fullname='%s', cusip='%s',fraction=%d,use_quote_source=%d,quote_source='%s',quote_tz='%s' WHERE guid='%s';",
-			namespace, mnemonic, fullname, cusip, fraction, quote_flag, quote_source, quote_tz, guid );
-		} else {
-			sprintf( cmdbuf,
-				"INSERT INTO commodities VALUES('%s', '%s', '%s','%s','%s',%d,'%d','%s','%s')\n",
-				guid, namespace, mnemonic, fullname, cusip, fraction, quote_flag, quote_source, quote_tz );
-		}
-		printf( "%s\n", cmdbuf );
-		gnc_gda_execute_sql( be, cmdbuf );
-    }
+	(void)gnc_gda_do_db_operation( be,
+						(inst->do_free ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+						"commodities",
+						col_conversion_table );
 }
 
+static void
+commit_commodity( GncGdaBackend* be, QofInstance* inst )
+{
+	do_db_commodity( be, inst, FALSE );
+}
+
 /* ================================================================= */
 void
 gnc_gda_init_commodity_handler( void )

Modified: gnucash/branches/gda-dev/src/backend/gda/gnc-commodity-gda.h
===================================================================
--- gnucash/branches/gda-dev/src/backend/gda/gnc-commodity-gda.h	2006-11-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-commodity-gda.h	2006-11-09 02:05:06 UTC (rev 15100)
@@ -20,9 +20,6 @@
 \********************************************************************/
 /** @file gnc-commodity-gda.h
  *  @brief load and save data to SQL via libgda
- *  @author Copyright (c) 2000 Gnumatic Inc.
- *  @author Copyright (c) 2002 Derek Atkins <warlord at MIT.EDU>
- *  @author Copyright (c) 2003 Linas Vepstas <linas at linas.org>
  *  @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
  *
  * This file implements the top-level QofBackend API for saving/

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-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-price-gda.c	2006-11-09 02:05:06 UTC (rev 15100)
@@ -20,9 +20,6 @@
 \********************************************************************/
 /** @file gnc-price-gda.c
  *  @brief load and save data to SQL 
- *  @author Copyright (c) 2000 Gnumatic Inc.
- *  @author Copyright (c) 2002 Derek Atkins <warlord at MIT.EDU>
- *  @author Copyright (c) 2003 Linas Vepstas <linas at linas.org>
  *  @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
  *
  * This file implements the top-level QofBackend API for saving/
@@ -36,51 +33,180 @@
 #include <libintl.h>
 #include <locale.h>
 #include <stdio.h>
-#include <fcntl.h>
 #include <limits.h>
-#include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <errno.h>
 #include <string.h>
-#include <dirent.h>
 #include <time.h>
 #include <libgda/libgda.h>
 
 #include "qof.h"
-#include "qofquery-p.h"
-#include "qofquerycore-p.h"
-#include "TransLog.h"
 #include "gnc-engine.h"
+#include "gnc-pricedb.h"
 
-#include "gnc-filepath-utils.h"
-
 #include "gnc-backend-gda.h"
-#include "gnc-gconf-utils.h"
 
 #include "gnc-price-gda.h"
 
-#ifndef HAVE_STRPTIME
-# include "strptime.h"
-#endif
-
 static QofLogModule log_module = GNC_MOD_BACKEND;
 
 /* ================================================================= */
+static GNCPrice*
+load_price( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+	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;
+
+	Account* pParent = NULL;
+	const gchar* code = NULL;
+	const gchar* description = NULL;
+	gnc_commodity* pCommodity;
+	gnc_commodity* pCurrency;
+
+	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 }
+	};
+
+	gnc_gda_load_object( be, pModel, col_conversion_table, row );
+
+	pCommodity = gnc_commodity_find_commodity_by_guid( &commodity_guid, pBook );
+	pCurrency = gnc_commodity_find_commodity_by_guid( &currency_guid, pBook );
+
+	pPrice = gnc_price_create( 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 );
+
+	return pPrice;
+}
+
+static void
+load_prices( GncGdaBackend* be )
+{
+	GError* error = NULL;
+
+	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 );
+	if( query == NULL ) {
+		printf( "SQL error: %s\n", error->message );
+		return;
+	}
+	error = NULL;
+	ret = gda_query_execute( query, NULL, FALSE, &error );
+
+	if( error != NULL ) {
+		printf( "SQL error: %s\n", error->message );
+	}
+	if( GDA_IS_DATA_MODEL( ret ) ) {
+		GdaDataModel* pModel = (GdaDataModel*)ret;
+		int numRows = gda_data_model_get_n_rows( pModel );
+		int r;
+		GNCPrice* pPrice;
+
+		for( r = 0; r < numRows; r++ ) {
+
+			pPrice = load_price( be, pModel, r );
+
+			if( pPrice != NULL ) {
+				gnc_pricedb_add_price( pPriceDB, pPrice );
+			}
+		}
+	}
+}
+
+/* ================================================================= */
+static gboolean
+price_exists_in_db( GncGdaBackend* be, const gchar* guid )
+{
+	gchar* cmdbuf;
+	int count;
+
+	cmdbuf = g_strdup_printf( "SELECT * FROM prices WHERE guid='%s';", guid );
+	count = gnc_gda_execute_select_get_count( be, cmdbuf );
+	g_free( cmdbuf );
+	if( count == 0 ) {
+		return FALSE;
+	} else {
+		return TRUE;
+	}
+}
+
+static void
+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 );
+}
+
+/* ================================================================= */
 void
 gnc_gda_init_price_handler( void )
 {
-#if 0
 	static GncGdaDataType_t be_data =
 	{
 		GNC_GDA_BACKEND_VERSION,
-		GNC_ID_ACCOUNT,
-		commit_account,		/* commit */
-		NULL				/* initial_load */
+		GNC_ID_PRICE,
+		commit_price,			/* commit */
+		load_prices				/* initial_load */
 	};
 
-	qof_object_register_backend( GNC_ID_ACCOUNT, GNC_GDA_BACKEND, &be_data );
-#endif
+	qof_object_register_backend( GNC_ID_PRICE, GNC_GDA_BACKEND, &be_data );
 }
 
 /* ========================== END OF FILE ===================== */

Modified: gnucash/branches/gda-dev/src/backend/gda/gnc-price-gda.h
===================================================================
--- gnucash/branches/gda-dev/src/backend/gda/gnc-price-gda.h	2006-11-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-price-gda.h	2006-11-09 02:05:06 UTC (rev 15100)
@@ -20,9 +20,6 @@
 \********************************************************************/
 /** @file gnc-price-gda.h
  *  @brief load and save data to SQL via libgda
- *  @author Copyright (c) 2000 Gnumatic Inc.
- *  @author Copyright (c) 2002 Derek Atkins <warlord at MIT.EDU>
- *  @author Copyright (c) 2003 Linas Vepstas <linas at linas.org>
  *  @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
  *
  * This file implements the top-level QofBackend API for saving/

Modified: gnucash/branches/gda-dev/src/backend/gda/gnc-transaction-gda.c
===================================================================
--- gnucash/branches/gda-dev/src/backend/gda/gnc-transaction-gda.c	2006-11-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-transaction-gda.c	2006-11-09 02:05:06 UTC (rev 15100)
@@ -20,9 +20,6 @@
 \********************************************************************/
 /** @file gnc-transaction-gda.c
  *  @brief load and save data to SQL 
- *  @author Copyright (c) 2000 Gnumatic Inc.
- *  @author Copyright (c) 2002 Derek Atkins <warlord at MIT.EDU>
- *  @author Copyright (c) 2003 Linas Vepstas <linas at linas.org>
  *  @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
  *
  * This file implements the top-level QofBackend API for saving/

Modified: gnucash/branches/gda-dev/src/backend/gda/gnc-transaction-gda.h
===================================================================
--- gnucash/branches/gda-dev/src/backend/gda/gnc-transaction-gda.h	2006-11-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/src/backend/gda/gnc-transaction-gda.h	2006-11-09 02:05:06 UTC (rev 15100)
@@ -20,9 +20,6 @@
 \********************************************************************/
 /** @file gnc-transaction-gda.h
  *  @brief load and save data to SQL via libgda
- *  @author Copyright (c) 2000 Gnumatic Inc.
- *  @author Copyright (c) 2002 Derek Atkins <warlord at MIT.EDU>
- *  @author Copyright (c) 2003 Linas Vepstas <linas at linas.org>
  *  @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
  *
  * This file implements the top-level QofBackend API for saving/

Modified: gnucash/branches/gda-dev/src/backend/gda/gncmod-backend-gda.c
===================================================================
--- gnucash/branches/gda-dev/src/backend/gda/gncmod-backend-gda.c	2006-11-08 22:43:59 UTC (rev 15099)
+++ gnucash/branches/gda-dev/src/backend/gda/gncmod-backend-gda.c	2006-11-09 02:05:06 UTC (rev 15100)
@@ -25,19 +25,19 @@
 static GNCModule engine;
 
 /* forward references */
-char *libgncmod_backend_gda_LTX_gnc_module_path(void);
-char *libgncmod_backend_gda_LTX_gnc_module_description(void);
+gchar *libgncmod_backend_gda_LTX_gnc_module_path(void);
+gchar *libgncmod_backend_gda_LTX_gnc_module_description(void);
 int libgncmod_backend_gda_LTX_gnc_module_init(int refcount);
 int libgncmod_backend_gda_LTX_gnc_module_end(int refcount);
 
 
-char *
+gchar *
 libgncmod_backend_gda_LTX_gnc_module_path(void) 
 {
   return g_strdup("gnucash/backend/gda");
 }
 
-char * 
+gchar * 
 libgncmod_backend_gda_LTX_gnc_module_description(void) 
 {
   return g_strdup("The GDA/SQL backend for GnuCash");



More information about the gnucash-changes mailing list