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, "e_flag },
- { "quote_source", CT_STRING, "e_source_name },
- { "quote_tz", CT_STRING, "e_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, "e_flag },
- { "quote_source", CT_STRING, "e_source },
- { "quote_tz", CT_STRING, "e_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, ¤cy_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( ¤cy_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, ¤cy_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