r16700 - gnucash/branches/gda-dev2/src - 1) Add gda backend code
Phil Longstaff
plongstaff at cvs.gnucash.org
Sun Dec 23 15:25:57 EST 2007
Author: plongstaff
Date: 2007-12-23 15:25:56 -0500 (Sun, 23 Dec 2007)
New Revision: 16700
Trac: http://svn.gnucash.org/trac/changeset/16700
Added:
gnucash/branches/gda-dev2/src/backend/gda/
gnucash/branches/gda-dev2/src/backend/gda/Makefile.am
gnucash/branches/gda-dev2/src/backend/gda/gnc-account-gda.c
gnucash/branches/gda-dev2/src/backend/gda/gnc-account-gda.h
gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-gda.c
gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-gda.h
gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-util-gda.c
gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-util-gda.h
gnucash/branches/gda-dev2/src/backend/gda/gnc-book-gda.c
gnucash/branches/gda-dev2/src/backend/gda/gnc-book-gda.h
gnucash/branches/gda-dev2/src/backend/gda/gnc-budget-gda.c
gnucash/branches/gda-dev2/src/backend/gda/gnc-budget-gda.h
gnucash/branches/gda-dev2/src/backend/gda/gnc-commodity-gda.c
gnucash/branches/gda-dev2/src/backend/gda/gnc-commodity-gda.h
gnucash/branches/gda-dev2/src/backend/gda/gnc-lots-gda.c
gnucash/branches/gda-dev2/src/backend/gda/gnc-lots-gda.h
gnucash/branches/gda-dev2/src/backend/gda/gnc-price-gda.c
gnucash/branches/gda-dev2/src/backend/gda/gnc-price-gda.h
gnucash/branches/gda-dev2/src/backend/gda/gnc-recurrence-gda.c
gnucash/branches/gda-dev2/src/backend/gda/gnc-recurrence-gda.h
gnucash/branches/gda-dev2/src/backend/gda/gnc-schedxaction-gda.c
gnucash/branches/gda-dev2/src/backend/gda/gnc-schedxaction-gda.h
gnucash/branches/gda-dev2/src/backend/gda/gnc-slots-gda.c
gnucash/branches/gda-dev2/src/backend/gda/gnc-slots-gda.h
gnucash/branches/gda-dev2/src/backend/gda/gnc-transaction-gda.c
gnucash/branches/gda-dev2/src/backend/gda/gnc-transaction-gda.h
gnucash/branches/gda-dev2/src/backend/gda/gncmod-backend-gda.c
gnucash/branches/gda-dev2/src/backend/gda/test/
gnucash/branches/gda-dev2/src/backend/gda/test/Makefile.am
gnucash/branches/gda-dev2/src/backend/gda/test/test-load-backend.c
gnucash/branches/gda-dev2/src/backend/xml/
gnucash/branches/gda-dev2/src/business/business-core/gda/
gnucash/branches/gda-dev2/src/business/business-core/gda/Makefile.am
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-address-gda.c
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-address-gda.h
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-bill-term-gda.c
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-bill-term-gda.h
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-customer-gda.c
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-customer-gda.h
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-employee-gda.c
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-employee-gda.h
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-entry-gda.c
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-entry-gda.h
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-invoice-gda.c
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-invoice-gda.h
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-job-gda.c
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-job-gda.h
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-order-gda.c
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-order-gda.h
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-vendor-gda.c
gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-vendor-gda.h
gnucash/branches/gda-dev2/src/business/business-core/gda/gncmod-business-backend-gda.c
gnucash/branches/gda-dev2/src/business/business-core/xml/
Removed:
gnucash/branches/gda-dev2/src/backend/file/
gnucash/branches/gda-dev2/src/business/business-core/file/
Log:
1) Add gda backend code
2) Rename file backend directories to xml
Added: gnucash/branches/gda-dev2/src/backend/gda/Makefile.am
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/Makefile.am (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/Makefile.am 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,63 @@
+SUBDIRS = . test
+
+# Now a shared library AND a GModule
+lib_LTLIBRARIES = libgnc-backend-gda-utils.la
+pkglib_LTLIBRARIES = libgncmod-backend-gda.la
+
+
+AM_CFLAGS = \
+ -I.. -I../.. \
+ -DLOCALE_DIR=\""$(datadir)/locale"\" \
+ -I${top_srcdir}/src/backend \
+ -I${top_srcdir}/src/engine \
+ -I${top_srcdir}/src/core-utils\
+ -I${top_srcdir}/lib/libc\
+ ${QOF_CFLAGS} \
+ ${GLIB_CFLAGS} \
+ ${LIBGDA_CFLAGS} \
+ ${GCONF_CFLAGS} \
+ ${WARN_CFLAGS}
+
+libgnc_backend_gda_utils_la_SOURCES = \
+ gnc-backend-util-gda.c \
+ gnc-account-gda.c \
+ gnc-book-gda.c \
+ gnc-budget-gda.c \
+ gnc-commodity-gda.c \
+ gnc-lots-gda.c \
+ gnc-price-gda.c \
+ gnc-recurrence-gda.c \
+ gnc-schedxaction-gda.c \
+ gnc-slots-gda.c \
+ gnc-transaction-gda.c
+
+libgncmod_backend_gda_la_SOURCES = \
+ gnc-backend-gda.c
+
+noinst_HEADERS = \
+ gnc-account-gda.h \
+ gnc-backend-gda.h \
+ gnc-backend-util-gda.h \
+ gnc-book-gda.h \
+ gnc-budget-gda.h \
+ gnc-commodity-gda.h \
+ gnc-lots-gda.h \
+ gnc-price-gda.h \
+ gnc-recurrence-gda.h \
+ gnc-schedxaction-gda.h \
+ gnc-slots-gda.h \
+ gnc-transaction-gda.h
+
+libgnc_backend_gda_utils_la_LIBADD = \
+ ${GLIB_LIBS} ${GCONF_LIBS} \
+ ${top_builddir}/src/engine/libgncmod-engine.la \
+ ${LIBGDA_LIBS}
+
+libgncmod_backend_gda_la_LDFLAGS = -module -avoid-version
+libgncmod_backend_gda_la_LIBADD = \
+ ${GLIB_LIBS} ${GCONF_LIBS} \
+ ${top_builddir}/src/engine/libgncmod-engine.la \
+ libgnc-backend-gda-utils.la \
+ ${LIBGDA_LIBS}
+
+INCLUDES = -DG_LOG_DOMAIN=\"gnc.backend.gda\"
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-account-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-account-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-account-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,314 @@
+/********************************************************************
+ * gnc-account-gda.c: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-account-gda.c
+ * @brief load and save data to SQL
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL db using libgda
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <libgda/libgda.h>
+
+#include "qof.h"
+#include "Account.h"
+#include "AccountP.h"
+#include "gnc-commodity.h"
+
+#include "gnc-backend-util-gda.h"
+
+#include "gnc-account-gda.h"
+#include "gnc-commodity-gda.h"
+#include "gnc-slots-gda.h"
+#include "gnc-transaction-gda.h"
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define TABLE_NAME "accounts"
+
+static gpointer get_parent( gpointer pObject, const QofParam* );
+static void set_parent( gpointer pObject, gpointer pValue );
+static void set_parent_guid( gpointer pObject, gpointer pValue );
+
+#define ACCOUNT_MAX_NAME_LEN 50
+#define ACCOUNT_MAX_TYPE_LEN 50
+#define ACCOUNT_MAX_CODE_LEN 100
+#define ACCOUNT_MAX_DESCRIPTION_LEN 500
+
+static col_cvt_t col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "name", CT_STRING, ACCOUNT_MAX_NAME_LEN, COL_NNUL, "name" },
+ { "account_type", CT_STRING, ACCOUNT_MAX_TYPE_LEN, COL_NNUL, NULL, ACCOUNT_TYPE_ },
+ { "commodity_guid", CT_COMMODITYREF, 0, COL_NNUL, "commodity" },
+ { "parent_guid", CT_GUID, 0, 0, NULL, NULL, get_parent, set_parent },
+ { "code", CT_STRING, ACCOUNT_MAX_CODE_LEN, 0, "code" },
+ { "description", CT_STRING, ACCOUNT_MAX_DESCRIPTION_LEN, 0, "description" },
+ { NULL }
+};
+static col_cvt_t parent_col_table[] =
+{
+ { "parent_guid", CT_GUID, 0, 0, NULL, NULL, NULL, set_parent_guid },
+ { NULL }
+};
+
+typedef struct {
+ Account* pAccount;
+ GUID guid;
+} account_parent_guid_struct;
+
+/* ================================================================= */
+
+static gpointer
+get_parent( gpointer pObject, const QofParam* param )
+{
+ const Account* pAccount = GNC_ACCOUNT(pObject);
+ const Account* pParent = gnc_account_get_parent( pAccount );
+ const GUID* parent_guid;
+
+ if( pParent == NULL ) {
+ parent_guid = NULL;
+ } else {
+ parent_guid = qof_instance_get_guid( QOF_INSTANCE(pParent) );
+ }
+
+ return (gpointer)parent_guid;
+}
+
+static void
+set_parent( gpointer pObject, gpointer pValue )
+{
+ Account* pAccount = GNC_ACCOUNT(pObject);
+ QofBook* pBook = qof_instance_get_book( QOF_INSTANCE(pAccount) );
+ GUID* guid = (GUID*)pValue;
+ Account* pParent;
+
+ if( guid != NULL ) {
+ pParent = xaccAccountLookup( guid, pBook );
+ if( pParent != NULL ) {
+ gnc_account_append_child( pParent, pAccount );
+ }
+ }
+}
+
+static void
+set_parent_guid( gpointer pObject, gpointer pValue )
+{
+ account_parent_guid_struct* s = (account_parent_guid_struct*)pObject;
+ GUID* guid = (GUID*)pValue;
+
+ s->guid = *guid;
+}
+
+static void
+load_balances( GncGdaBackend* be, Account* pAccount )
+{
+ gnc_numeric start_balance;
+ gnc_numeric cleared_balance;
+ gnc_numeric reconciled_balance;
+
+ gnc_gda_get_account_balances( be, pAccount, &start_balance, &cleared_balance, &reconciled_balance );
+
+ g_object_set( pAccount,
+ "end-balance", &start_balance,
+ "end-cleared-balance", &cleared_balance,
+ "end-reconciled-balance", &reconciled_balance,
+ NULL);
+}
+
+static Account*
+load_single_account( GncGdaBackend* be, GdaDataModel* pModel, int row,
+ GList** l_accounts_needing_parents )
+{
+ const GUID* guid;
+ GUID acc_guid;
+ Account* pAccount;
+
+ guid = gnc_gda_load_guid( be, pModel, row );
+ acc_guid = *guid;
+
+ pAccount = xaccAccountLookup( &acc_guid, be->primary_book );
+ if( pAccount == NULL ) {
+ pAccount = xaccMallocAccount( be->primary_book );
+ }
+ gnc_gda_load_object( be, pModel, row, GNC_ID_ACCOUNT, pAccount, col_table );
+ gnc_gda_slots_load( be, xaccAccountGetGUID( pAccount ),
+ qof_instance_get_slots( QOF_INSTANCE(pAccount) ) );
+ load_balances( be, pAccount );
+
+ qof_instance_mark_clean( QOF_INSTANCE(pAccount) );
+
+ /* If we don't have a parent, it might be because the parent account hasn't
+ been loaded yet. Remember the account and its parent guid for later. */
+ if( gnc_account_get_parent( pAccount ) == NULL ) {
+ account_parent_guid_struct* s = g_slice_new( account_parent_guid_struct );
+ s->pAccount = pAccount;
+ gnc_gda_load_object( be, pModel, row, GNC_ID_ACCOUNT, s, parent_col_table );
+ *l_accounts_needing_parents = g_list_prepend( *l_accounts_needing_parents, s );
+ }
+
+ return pAccount;
+}
+
+static void
+load_all_accounts( GncGdaBackend* be )
+{
+ static GdaQuery* query = NULL;
+ GdaObject* ret;
+ QofBook* pBook = be->primary_book;
+ gnc_commodity_table* pTable = gnc_commodity_table_get_table( pBook );
+
+ /* First time, create the query */
+ if( query == NULL ) {
+ query = gnc_gda_create_select_query( be, TABLE_NAME );
+ }
+
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+ Account* pAccount;
+ Account* parent;
+ GList* l_accounts_needing_parents = NULL;
+
+ for( r = 0; r < numRows; r++ ) {
+ pAccount = load_single_account( be, pModel, r, &l_accounts_needing_parents );
+
+#if 0
+ if( pAccount != NULL ) {
+
+ /* Backwards compatibility. If there's no parent, see if
+ * this account is of type ROOT. If not, find or create a
+ * ROOT account and make that the parent. */
+ parent = gnc_account_get_parent( pAccount );
+ if( parent == NULL ) {
+ int type;
+
+ type = xaccAccountGetType( pAccount );
+ if( type != ACCT_TYPE_ROOT ) {
+ Account* root;
+ root = gnc_book_get_root_account( pBook );
+ if( root == NULL ) {
+ root = gnc_account_create_root( pBook );
+ }
+ gnc_account_append_child( root, pAccount );
+ }
+ }
+ }
+#endif
+ }
+
+ /* While there are items on the list of accounts needing parents,
+ try to see if the parent has now been loaded. Theory says that if
+ items are removed from the front and added to the back if the
+ parent is still not available, then eventually, the list will
+ shrink to size 0. */
+ if( l_accounts_needing_parents != NULL ) {
+ gboolean progress_made = TRUE;
+
+ Account* pParent;
+ GList* elem;
+
+ while( progress_made ) {
+ progress_made = FALSE;
+ for( elem = l_accounts_needing_parents; elem != NULL; elem = g_list_next( elem ) ) {
+ account_parent_guid_struct* s = (account_parent_guid_struct*)elem->data;
+ const gchar* name = xaccAccountGetName( s->pAccount );
+ pParent = xaccAccountLookup( &s->guid, be->primary_book );
+ if( pParent != NULL ) {
+ gnc_account_append_child( pParent, s->pAccount );
+ l_accounts_needing_parents = g_list_delete_link( l_accounts_needing_parents, elem );
+ progress_made = TRUE;
+ }
+ }
+ }
+
+ /* Any accounts left over must be parented by the root account */
+ for( elem = l_accounts_needing_parents; elem != NULL; elem = g_list_next( elem ) ) {
+ account_parent_guid_struct* s = (account_parent_guid_struct*)elem->data;
+ Account* root;
+ root = gnc_book_get_root_account( pBook );
+ if( root == NULL ) {
+ root = gnc_account_create_root( pBook );
+ }
+ gnc_account_append_child( root, pAccount );
+ }
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_account_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, TABLE_NAME, col_table );
+}
+
+/* ================================================================= */
+void
+gnc_gda_save_account( GncGdaBackend* be, QofInstance* inst )
+{
+ Account* pAcc = GNC_ACCOUNT(inst);
+ const GUID* guid;
+
+ // If there is no commodity yet, this might be because a new account name has been entered directly
+ // into the register and an account window will be opened. The account info is not complete yet,
+ // but the name has been set, triggering this commit
+ if( xaccAccountGetCommodity( pAcc ) != NULL ) {
+ // Ensure the commodity is in the db
+ gnc_gda_save_commodity( be, xaccAccountGetCommodity( pAcc ) );
+
+ (void)gnc_gda_do_db_operation( be,
+ (qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+ TABLE_NAME,
+ GNC_ID_ACCOUNT, pAcc,
+ col_table );
+
+ // Now, commit or delete any slots
+ guid = qof_instance_get_guid( inst );
+ if( !qof_instance_get_destroying(inst) ) {
+ gnc_gda_slots_save( be, guid, qof_instance_get_slots( inst ) );
+ } else {
+ gnc_gda_slots_delete( be, guid );
+ }
+ }
+}
+
+/* ================================================================= */
+void
+gnc_gda_init_account_handler( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_ACCOUNT,
+ gnc_gda_save_account, /* commit */
+ load_all_accounts, /* initial_load */
+ create_account_tables /* create_tables */
+ };
+
+ qof_object_register_backend( GNC_ID_ACCOUNT, GNC_GDA_BACKEND, &be_data );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-account-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-account-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-account-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,38 @@
+/********************************************************************
+ * gnc-account-gda.h: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-account-gda.h
+ * @brief load and save accounts data to SQL via libgda
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_ACCOUNT_GDA_H_
+#define GNC_ACCOUNT_GDA_H_
+
+#include "qof.h"
+#include <gmodule.h>
+
+void gnc_gda_init_account_handler( void );
+void gnc_gda_save_account( GncGdaBackend* be, QofInstance* inst );
+
+#endif /* GNC_ACCOUNT_GDA_H_ */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,1067 @@
+/********************************************************************
+ * gnc-backend-gda.c: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-backend-gda.c
+ * @brief load and save data to SQL
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL db using libgda
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+
+#include <libgda/libgda.h>
+
+#include "qof.h"
+#include "qofquery-p.h"
+#include "qofquerycore-p.h"
+#include "TransLog.h"
+#include "gnc-engine.h"
+#include "SX-book.h"
+#include "Recurrence.h"
+
+#include "gnc-backend-util-gda.h"
+#include "gnc-gconf-utils.h"
+
+#include "gnc-account-gda.h"
+#include "gnc-book-gda.h"
+#include "gnc-budget-gda.h"
+#include "gnc-commodity-gda.h"
+#include "gnc-lots-gda.h"
+#include "gnc-price-gda.h"
+#include "gnc-pricedb.h"
+#include "gnc-recurrence-gda.h"
+#include "gnc-schedxaction-gda.h"
+#include "gnc-slots-gda.h"
+#include "gnc-transaction-gda.h"
+
+#include "gnc-backend-gda.h"
+
+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 );
+
+typedef struct {
+ QofIdType searchObj;
+ gpointer pCompiledQuery;
+} gnc_gda_query_info;
+
+/* callback structure */
+typedef struct {
+ gboolean ok;
+ GncGdaBackend* be;
+ QofInstance* inst;
+ QofQuery* pQuery;
+ gpointer pCompiledQuery;
+ gnc_gda_query_info* pQueryInfo;
+} gda_backend;
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define SQLITE_PROVIDER_NAME "SQLite"
+
+/* ================================================================= */
+
+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)
+{
+ GncGdaBackend *be = (GncGdaBackend*) be_start;
+ GError* error = NULL;
+ gda_backend be_data;
+ gchar* book_info;
+ gchar* dsn;
+ gchar* username = "";
+ gchar* password = "";
+
+ ENTER (" ");
+
+ be->pClient = gda_client_new();
+ be->pConnection = NULL;
+
+ /* Split book_id into provider and connection string. If there's no
+ provider, use "file" */
+ book_info = g_strdup( book_id );
+ dsn = strchr( book_info, ':' );
+ if( dsn != NULL ) {
+ *dsn = '\0';
+ dsn += 3; // Skip '://'
+
+ // String will be one of:
+ //
+ // sqlite:<filename>
+ // mysql:<dbname>
+ // pgsql:<dbname>
+ // @<gda_connectionname>
+
+ if( dsn[0] == '@' ) {
+ dsn++;
+
+ be->pConnection = gda_client_open_connection( be->pClient,
+ dsn,
+ username, password,
+ 0,
+ &error );
+ }
+ }
+
+ if( dsn == NULL || dsn[0] != '@' ) {
+ gchar* provider;
+ GList* provider_list;
+ GList* l;
+ gboolean provider_found;
+
+ if( dsn != NULL ) {
+ provider = dsn;
+ dsn = strchr( dsn, ':' );
+ *dsn = '\0';
+ dsn++;
+ } else {
+ provider = SQLITE_PROVIDER_NAME;
+ dsn = book_info;
+ }
+
+ // Get a list of all of the providers. If the requested provider is on the list, use it.
+ // Note that we need a case insensitive comparison here
+ provider_list = gda_config_get_provider_list();
+
+ provider_found = FALSE;
+ for( l = provider_list; l != NULL; l = l->next ) {
+ GdaProviderInfo* provider_info = (GdaProviderInfo*)l->data;
+
+ if( provider_info != NULL && g_ascii_strcasecmp( provider_info->id, provider ) == 0 ) {
+ provider_found = TRUE;
+ provider = provider_info->id;
+ break;
+ }
+ }
+
+ if( provider_found ) {
+ gchar* cnc;
+
+ // If the provider is SQLite, split the file name into DB_DIR and
+ // DB_NAME
+ if( strcmp( provider, SQLITE_PROVIDER_NAME ) == 0 ) {
+ gchar* dirname;
+ gchar* basename;
+
+ dirname = g_path_get_dirname( dsn );
+ basename = g_path_get_basename( dsn );
+
+ // Remove .db from the base name if it exists
+ if( g_str_has_suffix( basename, ".db" ) ) {
+ gchar* bn = g_strdup( basename );
+ gchar* suffix = g_strrstr( bn, ".db" );
+ *suffix = '\0';
+
+ cnc = g_strdup_printf( "DB_DIR=%s;DB_NAME=%s", dirname, bn );
+ g_free( bn );
+ } else {
+ cnc = g_strdup_printf( "DB_DIR=%s;DB_NAME=%s",
+ dirname, basename );
+ }
+ g_free( dirname );
+ g_free( basename );
+ } else {
+ cnc = g_strdup( dsn );
+ }
+
+ be->pConnection = gda_client_open_connection_from_string( be->pClient,
+ provider,
+ cnc,
+ username, password,
+ 0,
+ &error );
+
+ if( be->pConnection == NULL ) {
+ GdaServerOperation* op = gda_client_prepare_create_database(
+ be->pClient,
+ dsn,
+ provider );
+ if( op != NULL ) {
+ gboolean isOK;
+ isOK = gda_client_perform_create_database(
+ be->pClient,
+ op,
+ &error );
+ if( isOK ) {
+ be->pConnection = gda_client_open_connection_from_string(
+ be->pClient,
+ provider,
+ cnc,
+ username, password,
+ 0,
+ &error );
+ }
+ }
+ }
+ g_free( cnc );
+ }
+ }
+ g_free( book_info );
+
+ if( be->pConnection == NULL ) {
+ g_critical( "SQL error: %s\n", error->message );
+ qof_backend_set_error( be_start, ERR_BACKEND_NO_SUCH_DB );
+
+ LEAVE( " " );
+ 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 ) {
+ g_critical( "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 ) {
+ g_critical( "gda_dict_update_dbms_meta_data() error: %s\n", error->message );
+ }
+
+ LEAVE (" ");
+}
+
+/* ================================================================= */
+
+static void
+gnc_gda_session_end(QofBackend *be_start)
+{
+ GncGdaBackend *be = (GncGdaBackend*)be_start;
+ ENTER (" ");
+
+ if( be->pDict != NULL ) {
+ g_object_unref( G_OBJECT(be->pDict) );
+ be->pDict = NULL;
+ }
+ if( be->pConnection != NULL && gda_connection_is_opened( be->pConnection ) ) {
+ gda_connection_close( be->pConnection );
+ }
+ be->pConnection = NULL;
+ if( be->pClient != NULL ) {
+ g_object_unref( G_OBJECT(be->pClient ) );
+ be->pClient = NULL;
+ }
+
+ LEAVE (" ");
+}
+
+static void
+gnc_gda_destroy_backend(QofBackend *be)
+{
+ g_free(be);
+}
+
+/* ================================================================= */
+
+static void
+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;
+
+ g_return_if_fail( type != NULL && pData != NULL && be_data != NULL );
+ g_return_if_fail( pData->version == GNC_GDA_BACKEND_VERSION );
+ g_return_if_fail( g_ascii_strcasecmp( type, GNC_ID_BOOK ) != 0 );
+
+ if( pData->initial_load != NULL ) {
+ (pData->initial_load)( be_data->be );
+ }
+}
+
+static void
+gnc_gda_load(QofBackend* be_start, QofBook *book)
+{
+ GncGdaBackend *be = (GncGdaBackend*)be_start;
+ gda_backend be_data;
+ GncGdaDataType_t* pData;
+
+ ENTER( "be=%p, book=%p", be, book );
+
+ g_assert( be->primary_book == NULL );
+ be->primary_book = book;
+
+ /* Load any initial stuff */
+ be->loading = TRUE;
+
+ /* Some of this needs to happen in a certain order */
+ pData = qof_object_lookup_backend( GNC_ID_BOOK, GNC_GDA_BACKEND );
+ if( pData->initial_load != NULL ) {
+ (pData->initial_load)( be );
+ }
+
+ be_data.ok = FALSE;
+ be_data.be = be;
+ be_data.inst = NULL;
+ qof_object_foreach_backend( GNC_GDA_BACKEND, initial_load_cb, &be_data );
+
+ be->loading = FALSE;
+
+ // Mark the book as clean
+ qof_instance_mark_clean( QOF_INSTANCE(book) );
+
+ LEAVE( "" );
+}
+
+/* ================================================================= */
+
+static gint
+compare_namespaces(gconstpointer a, gconstpointer b)
+{
+ const gchar *sa = (const gchar *) a;
+ const gchar *sb = (const gchar *) b;
+ return(safe_strcmp(sa, sb));
+}
+
+static gint
+compare_commodity_ids(gconstpointer a, gconstpointer b)
+{
+ const gnc_commodity *ca = (const gnc_commodity *) a;
+ const gnc_commodity *cb = (const gnc_commodity *) b;
+ return(safe_strcmp(gnc_commodity_get_mnemonic(ca),
+ gnc_commodity_get_mnemonic(cb)));
+}
+
+static void
+save_commodities( GncGdaBackend* be, QofBook* book )
+{
+ gnc_commodity_table* tbl;
+ GList* namespaces;
+ GList* lp;
+
+ tbl = gnc_book_get_commodity_table( book );
+ namespaces = gnc_commodity_table_get_namespaces( tbl );
+ if( namespaces != NULL ) {
+ namespaces = g_list_sort( namespaces, compare_namespaces );
+ }
+ for( lp = namespaces; lp != NULL; lp = lp->next ) {
+ GList* comms;
+ GList* lp2;
+
+ comms = gnc_commodity_table_get_commodities( tbl, lp->data );
+ comms = g_list_sort( comms, compare_commodity_ids );
+
+ for( lp2 = comms; lp2 != NULL; lp2 = lp2->next ) {
+ gnc_gda_save_commodity( be, GNC_COMMODITY(lp2->data) );
+ }
+ }
+}
+
+static void
+save_account_tree( GncGdaBackend* be, Account* root )
+{
+ GList* descendants;
+ GList* node;
+
+ descendants = gnc_account_get_descendants( root );
+ for( node = descendants; node != NULL; node = g_list_next(node) ) {
+ gnc_gda_save_account( be, QOF_INSTANCE(GNC_ACCOUNT(node->data)) );
+ }
+ g_list_free( descendants );
+}
+
+static void
+save_accounts( GncGdaBackend* be, QofBook* book )
+{
+ save_account_tree( be, gnc_book_get_root_account( book ) );
+}
+
+static void
+write_budget( QofInstance* ent, gpointer data )
+{
+ GncGdaBackend* be = (GncGdaBackend*)data;
+
+ gnc_gda_save_budget( be, ent );
+}
+
+static void
+save_budgets( GncGdaBackend* be, QofBook* book )
+{
+ qof_collection_foreach( qof_book_get_collection( book, GNC_ID_BUDGET ),
+ write_budget, be );
+}
+
+static gboolean
+save_price( GNCPrice* p, gpointer data )
+{
+ GncGdaBackend* be = (GncGdaBackend*)data;
+
+ gnc_gda_save_price( be, QOF_INSTANCE(p) );
+
+ return TRUE;
+}
+
+static void
+save_prices( GncGdaBackend* be, QofBook* book )
+{
+ GNCPriceDB* priceDB = gnc_book_get_pricedb( book );
+
+ gnc_pricedb_foreach_price( priceDB, save_price, be, TRUE );
+}
+
+static int
+save_tx( Transaction* tx, gpointer data )
+{
+ GncGdaBackend* be = (GncGdaBackend*)data;
+
+ gnc_gda_save_transaction( be, QOF_INSTANCE(tx) );
+
+ return 0;
+}
+
+static void
+save_transactions( GncGdaBackend* be, QofBook* book )
+{
+ xaccAccountTreeForEachTransaction( gnc_book_get_root_account( book ),
+ save_tx,
+ (gpointer)be );
+}
+
+static void
+save_template_transactions( GncGdaBackend* be, QofBook* book )
+{
+ Account* ra;
+
+ ra = gnc_book_get_template_root( book );
+ if( gnc_account_n_descendants( ra ) > 0 ) {
+ save_account_tree( be, ra );
+ xaccAccountTreeForEachTransaction( ra, save_tx, (gpointer)be );
+ }
+}
+
+static void
+save_schedXactions( GncGdaBackend* be, QofBook* book )
+{
+ GList* schedXactions;
+ SchedXaction* tmpSX;
+
+ schedXactions = gnc_book_get_schedxactions( book )->sx_list;
+
+ for( ; schedXactions != NULL; schedXactions = schedXactions->next ) {
+ tmpSX = schedXactions->data;
+ gnc_gda_save_schedxaction( be, QOF_INSTANCE( tmpSX ) );
+ }
+}
+
+static void
+gnc_gda_sync_all( QofBackend* be, QofBook *book )
+{
+ GncGdaBackend *fbe = (GncGdaBackend *) be;
+ GdaDataModel* tables;
+ GError* error = NULL;
+ gint row;
+ gint numTables;
+ gda_backend be_data;
+
+ ENTER ("book=%p, primary=%p", book, fbe->primary_book);
+
+ /* Destroy the current contents of the database */
+ tables = gda_connection_get_schema( fbe->pConnection,
+ GDA_CONNECTION_SCHEMA_TABLES,
+ NULL,
+ &error );
+ if( error != NULL ) {
+ g_critical( "SQL error: %s\n", error->message );
+ }
+ numTables = gda_data_model_get_n_rows( tables );
+ for( row = 0; row < numTables; row++ ) {
+ const GValue* row_value;
+ const gchar* table_name;
+
+ row_value = gda_data_model_get_value_at( tables, 0, row );
+ table_name = g_value_get_string( row_value );
+ error = NULL;
+ if( !gda_drop_table( fbe->pConnection, table_name, &error ) ) {
+ g_critical( "Unable to drop table %s\n", table_name );
+ if( error != NULL ) {
+ g_critical( "SQL error: %s\n", error->message );
+ }
+ }
+ }
+
+ // Update the dictionary because new tables may exist
+ gda_dict_update_dbms_meta_data( fbe->pDict, 0, NULL, &error );
+ if( error != NULL ) {
+ g_critical( "gda_dict_update_dbms_meta_data() error: %s\n", error->message );
+ }
+
+ /* Create new tables */
+ be_data.ok = FALSE;
+ be_data.be = fbe;
+ 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( fbe->pDict, 0, NULL, &error );
+ if( error != NULL ) {
+ g_critical( "gda_dict_update_dbms_meta_data() error: %s\n", error->message );
+ }
+
+ /* Save all contents */
+ //save_commodities( fbe, book );
+ save_accounts( fbe, book );
+ save_prices( fbe, book );
+ save_transactions( fbe, book );
+ save_template_transactions( fbe, book );
+ save_schedXactions( fbe, book );
+ save_budgets( fbe, book );
+
+ LEAVE ("book=%p", book);
+}
+
+/* ================================================================= */
+/* Routines to deal with the creation of multiple books. */
+
+
+static void
+gnc_gda_begin_edit (QofBackend *be, QofInstance *inst)
+{
+}
+
+static void
+gnc_gda_rollback_edit (QofBackend *be, QofInstance *inst)
+{
+}
+
+static void
+commit_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 this has already been handled, or is not the correct handler, return */
+ g_return_if_fail( strcmp( pData->type_name, be_data->inst->e_type ) == 0 );
+ g_return_if_fail( !be_data->ok );
+
+ if( pData->commit != NULL ) {
+ (pData->commit)( be_data->be, be_data->inst );
+ be_data->ok = TRUE;
+ }
+}
+
+/* Commit_edit handler - find the correct backend handler for this object
+ * type and call its commit handler
+ */
+static void
+gnc_gda_commit_edit (QofBackend *be_start, QofInstance *inst)
+{
+ GncGdaBackend *be = (GncGdaBackend*)be_start;
+ gda_backend be_data;
+
+ ENTER( " " );
+
+ /* During initial load where objects are being created, don't commit
+ anything */
+
+ if( be->loading ) {
+ LEAVE( "" );
+ return;
+ }
+
+ g_debug( "gda_commit_edit(): %s dirty = %d, do_free=%d\n",
+ (inst->e_type ? inst->e_type : "(null)"),
+ qof_instance_get_dirty_flag(inst), qof_instance_get_destroying(inst) );
+
+ if( !qof_instance_get_dirty_flag(inst) && !qof_instance_get_destroying(inst) && GNC_IS_TRANS(inst) ) {
+ gnc_gda_transaction_commit_splits( be, GNC_TRANS(inst) );
+ }
+
+ if( !qof_instance_get_dirty_flag(inst) && !qof_instance_get_destroying(inst) ) return;
+
+ be_data.ok = FALSE;
+ be_data.be = be;
+ be_data.inst = inst;
+ qof_object_foreach_backend( GNC_GDA_BACKEND, commit_cb, &be_data );
+
+ if( !be_data.ok ) {
+ g_critical( "gnc_gda_commit_edit(): Unknown object type %s\n",
+ inst->e_type );
+ return;
+ }
+
+ qof_instance_mark_clean(inst);
+ qof_book_mark_saved( be->primary_book );
+
+ LEAVE( "" );
+}
+/* ---------------------------------------------------------------------- */
+
+/* Query processing */
+
+static const gchar*
+convert_search_obj( QofIdType objType )
+{
+ return (gchar*)objType;
+}
+
+static void
+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;
+ gchar val[GUID_ENCODING_LENGTH+1];
+
+ strcat( sql, "(" );
+ if( isInverted ) {
+ strcat( sql, "!" );
+ }
+
+ for( name = pParamPath; name != NULL; name = name->next ) {
+ if( name != pParamPath ) strcat( sql, "." );
+ strcat( sql, name->data );
+ }
+
+ if( pPredData->how == QOF_COMPARE_LT ) {
+ strcat( sql, "<" );
+ } else if( pPredData->how == QOF_COMPARE_LTE ) {
+ strcat( sql, "<=" );
+ } else if( pPredData->how == QOF_COMPARE_EQUAL ) {
+ strcat( sql, "=" );
+ } else if( pPredData->how == QOF_COMPARE_GT ) {
+ strcat( sql, ">" );
+ } else if( pPredData->how == QOF_COMPARE_GTE ) {
+ strcat( sql, ">=" );
+ } else if( pPredData->how == QOF_COMPARE_NEQ ) {
+ strcat( sql, "~=" );
+ } else {
+ strcat( sql, "??" );
+ }
+
+ if( strcmp( pPredData->type_name, "string" ) == 0 ) {
+ query_string_t pData = (query_string_t)pPredData;
+ strcat( sql, "'" );
+ strcat( sql, pData->matchstring );
+ strcat( sql, "'" );
+ } else if( strcmp( pPredData->type_name, "date" ) == 0 ) {
+ query_date_t pData = (query_date_t)pPredData;
+
+ (void)gnc_timespec_to_iso8601_buff( pData->date, val );
+ strcat( sql, "'" );
+ strncat( sql, val, 4+1+2+1+2 );
+ strcat( sql, "'" );
+ } else if( strcmp( pPredData->type_name, "numeric" ) == 0 ) {
+ query_numeric_t pData = (query_numeric_t)pPredData;
+
+ strcat( sql, "numeric" );
+ } else if( strcmp( pPredData->type_name, "guid" ) == 0 ) {
+ query_guid_t pData = (query_guid_t)pPredData;
+ (void)guid_to_string_buff( pData->guids->data, val );
+ strcat( sql, "'" );
+ strcat( sql, val );
+ strcat( sql, "'" );
+ } else if( strcmp( pPredData->type_name, "gint32" ) == 0 ) {
+ query_int32_t pData = (query_int32_t)pPredData;
+
+ sprintf( val, "%d", pData->val );
+ strcat( sql, val );
+ } else if( strcmp( pPredData->type_name, "gint64" ) == 0 ) {
+ query_int64_t pData = (query_int64_t)pPredData;
+
+ sprintf( val, "%" G_GINT64_FORMAT, pData->val );
+ strcat( sql, val );
+ } else if( strcmp( pPredData->type_name, "double" ) == 0 ) {
+ query_double_t pData = (query_double_t)pPredData;
+
+ sprintf( val, "%f", pData->val );
+ strcat( sql, val );
+ } else if( strcmp( pPredData->type_name, "boolean" ) == 0 ) {
+ query_boolean_t pData = (query_boolean_t)pPredData;
+
+ sprintf( val, "%d", pData->val );
+ strcat( sql, val );
+ } else {
+ g_assert( FALSE );
+ }
+
+ strcat( sql, ")" );
+}
+
+static void
+compile_query_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 );
+
+ g_return_if_fail( strcmp( type, be_data->pQueryInfo->searchObj ) == 0 );
+ g_return_if_fail( !be_data->ok );
+
+ if( pData->compile_query != NULL ) {
+ be_data->pQueryInfo->pCompiledQuery = (pData->compile_query)(
+ be_data->be,
+ be_data->pQuery );
+ be_data->ok = TRUE;
+ }
+}
+
+static gpointer
+gnc_gda_compile_query(QofBackend* pBEnd, QofQuery* pQuery)
+{
+ GncGdaBackend *be = (GncGdaBackend*)pBEnd;
+ GList* pBookList;
+ QofIdType searchObj;
+ gchar sql[1000];
+ gda_backend be_data;
+ gnc_gda_query_info* pQueryInfo;
+
+ ENTER( " " );
+
+ searchObj = qof_query_get_search_for( pQuery );
+
+ pQueryInfo = g_malloc( sizeof( gnc_gda_query_info ) );
+
+ // Try various objects first
+ be_data.ok = FALSE;
+ be_data.be = be;
+ be_data.pQuery = pQuery;
+ pQueryInfo->searchObj = searchObj;
+ be_data.pQueryInfo = pQueryInfo;
+
+ qof_object_foreach_backend( GNC_GDA_BACKEND, compile_query_cb, &be_data );
+ if( be_data.ok ) {
+ LEAVE( "" );
+ return be_data.pQueryInfo;
+ }
+
+ pBookList = qof_query_get_books( pQuery );
+
+ /* Convert search object type to table name */
+ sprintf( sql, "SELECT * from %s", convert_search_obj( searchObj ) );
+ if( !qof_query_has_terms( pQuery ) ) {
+ strcat( sql, ";" );
+ } else {
+ GList* pOrTerms = qof_query_get_terms( pQuery );
+ GList* orTerm;
+
+ strcat( sql, " WHERE " );
+
+ for( orTerm = pOrTerms; orTerm != NULL; orTerm = orTerm->next ) {
+ GList* pAndTerms = (GList*)orTerm->data;
+ GList* andTerm;
+
+ if( orTerm != pOrTerms ) strcat( sql, " OR " );
+ strcat( sql, "(" );
+ for( andTerm = pAndTerms; andTerm != NULL; andTerm = andTerm->next ) {
+ if( andTerm != pAndTerms ) strcat( sql, " AND " );
+ handle_and_term( (QofQueryTerm*)andTerm->data, sql );
+ }
+ strcat( sql, ")" );
+ }
+ }
+
+ g_debug( "Compiled: %s\n", sql );
+ pQueryInfo->pCompiledQuery = g_strdup( sql );
+
+ LEAVE( "" );
+
+ return pQueryInfo;
+}
+
+static void
+free_query_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 );
+ g_return_if_fail( strcmp( type, be_data->pQueryInfo->searchObj ) == 0 );
+
+ g_return_if_fail( !be_data->ok );
+
+ if( pData->free_query != NULL ) {
+ (pData->free_query)( be_data->be, be_data->pCompiledQuery );
+ be_data->ok = TRUE;
+ }
+}
+
+static void
+gnc_gda_free_query(QofBackend* pBEnd, gpointer pQuery)
+{
+ GncGdaBackend *be = (GncGdaBackend*)pBEnd;
+ gnc_gda_query_info* pQueryInfo = (gnc_gda_query_info*)pQuery;
+ gda_backend be_data;
+
+ ENTER( " " );
+
+ // Try various objects first
+ be_data.ok = FALSE;
+ be_data.be = be;
+ be_data.pCompiledQuery = pQuery;
+ be_data.pQueryInfo = pQueryInfo;
+
+ qof_object_foreach_backend( GNC_GDA_BACKEND, free_query_cb, &be_data );
+ if( be_data.ok ) {
+ LEAVE( "" );
+ return;
+ }
+
+ g_debug( "gda_free_query(): %s\n", (gchar*)pQueryInfo->pCompiledQuery );
+ g_free( pQueryInfo->pCompiledQuery );
+ g_free( pQueryInfo );
+
+ LEAVE( "" );
+}
+
+static void
+run_query_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 );
+ g_return_if_fail( strcmp( type, be_data->pQueryInfo->searchObj ) == 0 );
+
+ g_return_if_fail( !be_data->ok );
+
+ if( pData->run_query != NULL ) {
+ (pData->run_query)( be_data->be, be_data->pCompiledQuery );
+ be_data->ok = TRUE;
+ }
+}
+
+static void
+gnc_gda_run_query(QofBackend* pBEnd, gpointer pQuery)
+{
+ GncGdaBackend *be = (GncGdaBackend*)pBEnd;
+ gnc_gda_query_info* pQueryInfo = (gnc_gda_query_info*)pQuery;
+ gda_backend be_data;
+
+ g_return_if_fail( !be->in_query );
+
+ ENTER( " " );
+
+ be->loading = TRUE;
+ be->in_query = TRUE;
+
+ qof_event_suspend();
+
+ // Try various objects first
+ be_data.ok = FALSE;
+ be_data.be = be;
+ be_data.pCompiledQuery = pQueryInfo->pCompiledQuery;
+ be_data.pQueryInfo = pQueryInfo;
+
+ qof_object_foreach_backend( GNC_GDA_BACKEND, run_query_cb, &be_data );
+ be->loading = FALSE;
+ be->in_query = FALSE;
+ qof_event_resume();
+// if( be_data.ok ) {
+// LEAVE( "" );
+// return;
+// }
+
+ // Mark the book as clean
+ qof_instance_mark_clean( QOF_INSTANCE(be->primary_book) );
+
+// g_debug( "gda_run_query(): %s\n", (gchar*)pQueryInfo->pCompiledQuery );
+
+ LEAVE( "" );
+}
+
+/* ================================================================= */
+static void
+gnc_gda_init_object_handlers( void )
+{
+ gnc_gda_init_book_handler();
+ gnc_gda_init_commodity_handler();
+ gnc_gda_init_account_handler();
+ gnc_gda_init_budget_handler();
+ gnc_gda_init_price_handler();
+ gnc_gda_init_transaction_handler();
+ gnc_gda_init_slots_handler();
+ gnc_gda_init_recurrence_handler();
+ gnc_gda_init_schedxaction_handler();
+ gnc_gda_init_lot_handler();
+}
+
+/* ================================================================= */
+
+static QofBackend*
+gnc_gda_backend_new(void)
+{
+ GncGdaBackend *gnc_be;
+ QofBackend *be;
+ static gboolean initialized = FALSE;
+
+ gnc_be = g_new0(GncGdaBackend, 1);
+ be = (QofBackend*) gnc_be;
+ qof_backend_init(be);
+
+ be->session_begin = gnc_gda_session_begin;
+ be->session_end = gnc_gda_session_end;
+ be->destroy_backend = gnc_gda_destroy_backend;
+
+ be->load = gnc_gda_load;
+ be->save_may_clobber_data = NULL;
+
+ /* The gda backend treats accounting periods transactionally. */
+ be->begin = gnc_gda_begin_edit;
+ be->commit = gnc_gda_commit_edit;
+ be->rollback = gnc_gda_rollback_edit;
+
+ /* The gda backend uses queries to load data ... */
+ be->compile_query = gnc_gda_compile_query;
+ be->free_query = gnc_gda_free_query;
+ be->run_query = gnc_gda_run_query;
+
+ be->counter = NULL;
+
+ /* The gda backend will not be multi-user (for now)... */
+ be->events_pending = NULL;
+ be->process_events = NULL;
+
+ be->sync = gnc_gda_sync_all;
+ be->load_config = NULL;
+ be->get_config = NULL;
+
+ be->export = NULL;
+
+ gnc_be->primary_book = NULL;
+
+ if( !initialized ) {
+ gda_init( "gnucash", "2.0", 0, NULL );
+ gnc_gda_init_object_handlers();
+ gnc_gda_register_standard_col_type_handlers();
+ initialized = TRUE;
+ }
+
+ return be;
+}
+
+static void
+gnc_gda_provider_free (QofBackendProvider *prov)
+{
+ prov->provider_name = NULL;
+ prov->access_method = NULL;
+ g_free (prov);
+}
+
+/*
+ * Checks to see whether the file is an sqlite file or not
+ *
+ */
+static gboolean
+gnc_gda_check_sqlite_file(const gchar *path)
+{
+ FILE* f;
+ gchar buf[50];
+
+ // BAD if the path is null
+ if( path == NULL ) {
+ return FALSE;
+ }
+
+ if( g_str_has_suffix( path, ".db" ) ) {
+ f = g_fopen( path, "r" );
+
+ // OK if the file doesn't exist - new file
+ if( f == NULL ) {
+ return TRUE;
+ }
+
+ // OK if file has the correct header
+ fread( buf, sizeof(buf), 1, f );
+ fclose( f );
+ if( g_str_has_prefix( buf, "SQLite format" ) ) {
+ return TRUE;
+ }
+ } else {
+ f = g_fopen( path, "r" );
+
+ // BAD if the file exists - not ours
+ if( f != NULL ) {
+ fclose( f );
+ return FALSE;
+ }
+
+ // OK - new file
+ return TRUE;
+ }
+
+ // Otherwise, BAD
+ return FALSE;
+}
+
+G_MODULE_EXPORT void
+qof_backend_module_init(void)
+{
+ QofBackendProvider *prov;
+
+ prov = g_new0 (QofBackendProvider, 1);
+ prov->provider_name = "GnuCash LibGDA Backend";
+ prov->access_method = "gda";
+ prov->partial_book_supported = FALSE;
+ prov->backend_new = gnc_gda_backend_new;
+ prov->provider_free = gnc_gda_provider_free;
+ prov->check_data_type = NULL;
+ qof_backend_register_provider (prov);
+
+ prov = g_new0 (QofBackendProvider, 1);
+ prov->provider_name = "GnuCash LibGDA Backend";
+ prov->access_method = "file";
+ prov->partial_book_supported = FALSE;
+ prov->backend_new = gnc_gda_backend_new;
+ prov->provider_free = gnc_gda_provider_free;
+ prov->check_data_type = gnc_gda_check_sqlite_file;
+ qof_backend_register_provider (prov);
+}
+
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,81 @@
+/********************************************************************
+ * gnc-backend-gda.h: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-backend-gda.h
+ * @brief load and save data to SQL via libgda
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_BACKEND_GDA_H_
+#define GNC_BACKEND_GDA_H_
+
+#include "qof.h"
+#include <gmodule.h>
+
+#if 0
+#include "qofbackend-p.h"
+struct GncGdaBackend_struct
+{
+ QofBackend be;
+
+ GdaClient* pClient;
+ GdaConnection* pConnection;
+ GdaDict* pDict;
+
+ QofBook *primary_book; /* The primary, main open book */
+ gboolean loading; /* We are performing an initial load */
+ gboolean in_query;
+};
+typedef struct GncGdaBackend_struct GncGdaBackend;
+
+/**
+ * Struct used to pass in a new data type for GDA storage. This contains
+ * the set of callbacks to read and write GDA for new data objects.. New
+ * types should register an instance of this object with the engine.
+ *
+ * commit() - commit an object to the db
+ * initial_load() - load stuff when new db opened
+ */
+#define GNC_GDA_BACKEND "gnc:gda:1"
+#define GNC_GDA_BACKEND_VERSION 1
+typedef struct
+{
+ int version; /* backend version number */
+ const gchar * type_name; /* The XML tag for this type */
+
+ void (*commit)( GncGdaBackend* pBackend, QofInstance* inst );
+ void (*initial_load)( GncGdaBackend* pBackend );
+ void (*create_tables)( GncGdaBackend* pBackend );
+ gpointer (*compile_query)( GncGdaBackend* pBackend, QofQuery* pQuery );
+ void (*run_query)( GncGdaBackend* pBackend, gpointer pQuery );
+ void (*free_query)( GncGdaBackend* pBackend, gpointer pQuery );
+} GncGdaDataType_t;
+#endif
+
+// This is now a static inside the module
+//QofBackend * libgncmod_backend_gda_LTX_gnc_backend_new(void);
+
+G_MODULE_EXPORT void
+qof_backend_module_init(void);
+
+#endif /* GNC_BACKEND_GDA_H_ */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-util-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-util-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-util-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,1719 @@
+/********************************************************************
+ * gnc-backend-util-gda.c: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-backend-util-gda.c
+ * @brief load and save data to SQL - utility functions
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file contains utility routines to support saving/restoring
+ * data to/from an SQL db using libgda
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.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-commodity.h"
+
+#include "gnc-backend-util-gda.h"
+#include "gnc-gconf-utils.h"
+
+typedef struct {
+ QofIdType searchObj;
+ gpointer pCompiledQuery;
+} gnc_gda_query_info;
+
+/* callback structure */
+typedef struct {
+ gboolean ok;
+ GncGdaBackend* be;
+ QofInstance* inst;
+ QofQuery* pQuery;
+ gpointer pCompiledQuery;
+ gnc_gda_query_info* pQueryInfo;
+} gda_backend;
+
+#if 0
+typedef void (*GNC_GDA_LOAD_FN)( GncGdaBackend* be, GdaDataModel* pModel, gint row,
+ QofSetterFunc setter, gpointer pObject,
+ const col_cvt_t* table );
+typedef void (*GNC_GDA_CREATE_COL_FN)( GdaServerProvider* server,
+ GdaConnection* cnn, xmlNodePtr array_data,
+ const col_cvt_t* table_row, gboolean pkey );
+typedef void (*GNC_GDA_GET_GVALUE_QUERY_FN)( GncGdaBackend* be,
+ QofIdTypeConst obj_name, gpointer pObject,
+ const col_cvt_t* table_row, GdaQuery* query );
+typedef GdaQueryCondition* (*GNC_GDA_GET_GVALUE_COND_FN)( GncGdaBackend* be,
+ QofIdTypeConst obj_name, gpointer pObject,
+ const col_cvt_t* table_row, GdaQuery* query );
+
+typedef struct {
+ GNC_GDA_LOAD_FN load_fn;
+ GNC_GDA_CREATE_COL_FN create_col_fn;
+ GNC_GDA_GET_GVALUE_QUERY_FN get_gvalue_query_fn;
+ GNC_GDA_GET_GVALUE_COND_FN get_gvalue_cond_fn;
+} col_type_handler_t;
+#endif
+
+/* ================================================================= */
+void
+gnc_gda_add_field_to_query( GdaQuery* query, const gchar* col_name, const GValue* value )
+{
+ GdaQueryField* field;
+ GdaQueryField* field_value;
+
+ field = gda_query_field_field_new( query, col_name );
+ gda_query_field_set_visible( field, TRUE );
+
+ field_value = gda_query_field_value_new( query, G_VALUE_TYPE(value) );
+ gda_query_field_set_visible( field_value, TRUE );
+ gda_query_field_value_set_value( GDA_QUERY_FIELD_VALUE(field_value), value );
+ g_object_set( field, "value-provider", field_value, NULL );
+ g_object_unref( G_OBJECT(field_value) );
+
+ gda_entity_add_field( GDA_ENTITY(query), GDA_ENTITY_FIELD(field) );
+ g_object_unref( G_OBJECT(field) );
+}
+
+GdaQueryCondition*
+gnc_gda_create_condition_from_field( GdaQuery* query, const gchar* col_name,
+ const GValue* value )
+{
+ GdaQueryCondition* cond;
+ GdaQueryField* key;
+ GdaQueryField* key_value;
+
+ cond = gda_query_condition_new( query, GDA_QUERY_CONDITION_LEAF_EQUAL );
+
+ key = gda_query_field_field_new( query, col_name );
+ gda_query_field_set_visible( key, TRUE );
+ gda_query_condition_leaf_set_operator( cond,
+ GDA_QUERY_CONDITION_OP_LEFT,
+ GDA_QUERY_FIELD(key) );
+ g_object_unref( G_OBJECT(key) );
+
+ key_value = gda_query_field_value_new( query, G_VALUE_TYPE(value) );
+ gda_query_field_set_visible( key_value, TRUE );
+ gda_query_condition_leaf_set_operator( cond, GDA_QUERY_CONDITION_OP_RIGHT,
+ GDA_QUERY_FIELD(key_value) );
+ g_object_unref( G_OBJECT(key_value) );
+
+ gda_query_field_value_set_value( GDA_QUERY_FIELD_VALUE(key_value), value );
+
+ return cond;
+}
+/* ----------------------------------------------------------------- */
+QofAccessFunc
+gnc_gda_get_getter( QofIdTypeConst obj_name, const col_cvt_t* table_row )
+{
+ QofAccessFunc getter;
+
+ if( table_row->param_name != NULL ) {
+ getter = qof_class_get_parameter_getter( obj_name,
+ table_row->param_name );
+ } else {
+ getter = table_row->getter;
+ }
+
+ return getter;
+}
+
+static void
+load_string( const GncGdaBackend* be, GdaDataModel* pModel, gint row,
+ QofSetterFunc setter, gpointer pObject,
+ const col_cvt_t* table )
+{
+ const GValue* val;
+ const gchar* s;
+
+ 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 );
+ }
+ if( table->gobj_param_name != NULL ) {
+ g_object_set( pObject, table->gobj_param_name, s, NULL );
+ } else {
+ (*setter)( pObject, (const gpointer)s );
+ }
+}
+
+static void
+get_gvalue_string( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GValue* value )
+{
+ QofAccessFunc getter;
+ gchar* s;
+
+ memset( value, 0, sizeof( GValue ) );
+ if( table_row->gobj_param_name != NULL ) {
+ g_object_get( pObject, table_row->gobj_param_name, &s, NULL );
+ } else {
+ getter = gnc_gda_get_getter( obj_name, table_row );
+ s = (gchar*)(*getter)( pObject, NULL );
+ }
+ if( s ) {
+ g_value_init( value, G_TYPE_STRING );
+ g_value_set_string( value, s );
+ }
+}
+
+static void
+get_gvalue_string_for_query( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_string( be, obj_name, pObject, table_row, &value );
+ gnc_gda_add_field_to_query( query, table_row->col_name, &value );
+}
+
+static GdaQueryCondition*
+get_gvalue_string_cond( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_string( be, obj_name, pObject, table_row, &value );
+ return gnc_gda_create_condition_from_field( query, table_row->col_name,
+ &value );
+}
+
+static void
+create_string_col( GdaServerProvider* server, GdaConnection* cnn,
+ xmlNodePtr array_data, const col_cvt_t* table_row, gboolean pkey )
+{
+ const gchar* dbms_type;
+
+ dbms_type = gda_server_provider_get_default_dbms_type( server,
+ cnn, G_TYPE_STRING );
+ gnc_gda_add_table_column( server, cnn, array_data, table_row->col_name,
+ dbms_type, table_row->size, table_row->flags | pkey ? COL_PKEY : 0 );
+}
+
+static col_type_handler_t string_handler
+ = { load_string, create_string_col,
+ get_gvalue_string_for_query, get_gvalue_string_cond };
+/* ----------------------------------------------------------------- */
+
+static void
+load_int( const GncGdaBackend* be, 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 );
+ if( gda_value_is_null( val ) ) {
+ int_value = 0;
+ } else {
+ int_value = g_value_get_int( val );
+ }
+ if( table->gobj_param_name != NULL ) {
+ g_object_set( pObject, table->gobj_param_name, int_value, NULL );
+ } else {
+ (*setter)( pObject, GINT_TO_POINTER(int_value) );
+ }
+}
+
+static void
+get_gvalue_int( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GValue* value )
+{
+ gint int_value;
+ QofAccessFunc getter;
+
+ memset( value, 0, sizeof( GValue ) );
+
+ getter = gnc_gda_get_getter( obj_name, table_row );
+ int_value = GPOINTER_TO_INT((*getter)( pObject, NULL ));
+ g_value_init( value, G_TYPE_INT );
+ g_value_set_int( value, int_value );
+}
+
+static void
+get_gvalue_int_for_query( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_int( be, obj_name, pObject, table_row, &value );
+ gnc_gda_add_field_to_query( query, table_row->col_name, &value );
+}
+
+static GdaQueryCondition*
+get_gvalue_int_cond( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_int( be, obj_name, pObject, table_row, &value );
+ return gnc_gda_create_condition_from_field( query, table_row->col_name, &value );
+}
+
+static void
+create_int_col( GdaServerProvider* server, GdaConnection* cnn,
+ xmlNodePtr array_data, const col_cvt_t* table_row, gboolean pkey )
+{
+ const gchar* dbms_type;
+
+ dbms_type = gda_server_provider_get_default_dbms_type( server,
+ cnn, G_TYPE_INT );
+ gnc_gda_add_table_column( server, cnn, array_data, table_row->col_name,
+ dbms_type, table_row->size, table_row->flags | pkey ? COL_PKEY : 0 );
+}
+
+static col_type_handler_t int_handler =
+ { load_int, create_int_col,
+ get_gvalue_int_for_query, get_gvalue_int_cond };
+/* ----------------------------------------------------------------- */
+
+static void
+load_boolean( const GncGdaBackend* be, 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 );
+ if( gda_value_is_null( val ) ) {
+ int_value = 0;
+ } else {
+ int_value = g_value_get_int( val );
+ }
+ if( table->gobj_param_name != NULL ) {
+ g_object_set( pObject, table->gobj_param_name, int_value, NULL );
+ } else {
+ (*setter)( pObject, GINT_TO_POINTER(int_value) );
+ }
+}
+
+static void
+get_gvalue_boolean( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GValue* value )
+{
+ gint int_value;
+ QofAccessFunc getter;
+
+ memset( value, 0, sizeof( GValue ) );
+
+ getter = gnc_gda_get_getter( obj_name, table_row );
+ int_value = GPOINTER_TO_INT((*getter)( pObject, NULL ));
+ g_value_init( value, G_TYPE_INT );
+ g_value_set_int( value, int_value );
+}
+
+static void
+get_gvalue_boolean_for_query( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_int( be, obj_name, pObject, table_row, &value );
+ gnc_gda_add_field_to_query( query, table_row->col_name, &value );
+}
+
+static GdaQueryCondition*
+get_gvalue_boolean_cond( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_int( be, obj_name, pObject, table_row, &value );
+ return gnc_gda_create_condition_from_field( query, table_row->col_name, &value );
+}
+
+static void
+create_boolean_col( GdaServerProvider* server, GdaConnection* cnn,
+ xmlNodePtr array_data, const col_cvt_t* table_row, gboolean pkey )
+{
+ const gchar* dbms_type;
+
+ dbms_type = gda_server_provider_get_default_dbms_type( server,
+ cnn, G_TYPE_INT );
+ gnc_gda_add_table_column( server, cnn, array_data, table_row->col_name,
+ dbms_type, table_row->size, table_row->flags | pkey ? COL_PKEY : 0 );
+}
+
+static col_type_handler_t boolean_handler =
+ { load_boolean, create_boolean_col,
+ get_gvalue_boolean_for_query, get_gvalue_boolean_cond };
+/* ----------------------------------------------------------------- */
+
+static void
+load_int64( const GncGdaBackend* be, GdaDataModel* pModel, gint row,
+ QofSetterFunc setter, gpointer pObject,
+ const col_cvt_t* table )
+{
+ const GValue* val;
+ gint64 i64_value;
+
+ val = gda_data_model_get_value_at_col_name( pModel, table->col_name, row );
+ if( gda_value_is_null( val ) ) {
+ (*setter)( pObject, NULL );
+ } else {
+ i64_value = g_value_get_int64( val );
+ (*setter)( pObject, (gpointer)&i64_value );
+ }
+}
+
+static void
+get_gvalue_int64( const GncGdaBackend* be, QofIdTypeConst obj_name, const gpointer pObject,
+ const col_cvt_t* table_row, GValue* value )
+{
+ gint64* pInt64;
+ gint64 i64_value;
+ QofAccessFunc getter;
+
+ memset( value, 0, sizeof( GValue ) );
+ getter = gnc_gda_get_getter( obj_name, table_row );
+ pInt64 = (*getter)( pObject, NULL );
+ if( pInt64 != NULL ) {
+ i64_value = *pInt64;
+ g_value_init( value, G_TYPE_INT64 );
+ g_value_set_int64( value, i64_value );
+ }
+}
+
+static void
+get_gvalue_int64_for_query( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_int64( be, obj_name, pObject, table_row, &value );
+ gnc_gda_add_field_to_query( query, table_row->col_name, &value );
+}
+
+static GdaQueryCondition*
+get_gvalue_int64_cond( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_int64( be, obj_name, pObject, table_row, &value );
+ return gnc_gda_create_condition_from_field( query, table_row->col_name, &value );
+}
+
+static void
+create_int64_col( GdaServerProvider* server, GdaConnection* cnn,
+ xmlNodePtr array_data, const col_cvt_t* table_row, gboolean pkey )
+{
+ const gchar* dbms_type;
+
+ dbms_type = gda_server_provider_get_default_dbms_type( server,
+ cnn, G_TYPE_INT64 );
+ gnc_gda_add_table_column( server, cnn, array_data, table_row->col_name,
+ dbms_type, table_row->size, table_row->flags | pkey ? COL_PKEY : 0 );
+}
+
+static col_type_handler_t int64_handler =
+ { load_int64, create_int64_col,
+ get_gvalue_int64_for_query, get_gvalue_int64_cond };
+/* ----------------------------------------------------------------- */
+
+static void
+load_double( const GncGdaBackend* be, GdaDataModel* pModel, gint row,
+ QofSetterFunc setter, gpointer pObject,
+ const col_cvt_t* table )
+{
+ const GValue* val;
+ gdouble d_value;
+
+ val = gda_data_model_get_value_at_col_name( pModel, table->col_name, row );
+ if( gda_value_is_null( val ) ) {
+ (*setter)( pObject, (gpointer)NULL );
+ } else {
+ d_value = g_value_get_double( val );
+ (*setter)( pObject, (gpointer)&d_value );
+ }
+}
+
+static void
+get_gvalue_double( const GncGdaBackend* be, QofIdTypeConst obj_name, const gpointer pObject,
+ const col_cvt_t* table_row, GValue* value )
+{
+ QofAccessFunc getter;
+ gdouble* pDouble;
+ gdouble d_value;
+
+ memset( value, 0, sizeof( GValue ) );
+
+ getter = gnc_gda_get_getter( obj_name, table_row );
+ pDouble = (*getter)( pObject, NULL );
+ if( pDouble != NULL ) {
+ d_value = *pDouble;
+ g_value_init( value, G_TYPE_DOUBLE );
+ g_value_set_double( value, d_value );
+ }
+}
+
+static void
+get_gvalue_double_for_query( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_double( be, obj_name, pObject, table_row, &value );
+ gnc_gda_add_field_to_query( query, table_row->col_name, &value );
+}
+
+static GdaQueryCondition*
+get_gvalue_double_cond( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_double( be, obj_name, pObject, table_row, &value );
+ return gnc_gda_create_condition_from_field( query, table_row->col_name, &value );
+}
+
+static void
+create_double_col( GdaServerProvider* server, GdaConnection* cnn,
+ xmlNodePtr array_data, const col_cvt_t* table_row, gboolean pkey )
+{
+ const gchar* dbms_type;
+
+ dbms_type = gda_server_provider_get_default_dbms_type( server,
+ cnn, G_TYPE_INT64 );
+ gnc_gda_add_table_column( server, cnn, array_data, table_row->col_name,
+ dbms_type, table_row->size, table_row->flags | pkey ? COL_PKEY : 0 );
+}
+
+static col_type_handler_t double_handler =
+ { load_double, create_double_col,
+ get_gvalue_double_for_query, get_gvalue_double_cond };
+/* ----------------------------------------------------------------- */
+
+static void
+load_guid( const GncGdaBackend* be, 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;
+ }
+ if( table->gobj_param_name != NULL ) {
+ g_object_set( pObject, table->gobj_param_name, pGuid, NULL );
+ } else {
+ (*setter)( pObject, (const gpointer)pGuid );
+ }
+}
+
+static void
+get_gvalue_guid( const GncGdaBackend* be, QofIdTypeConst obj_name, const gpointer pObject,
+ const col_cvt_t* table_row, GValue* value )
+{
+ QofAccessFunc getter;
+ const GUID* guid;
+ gchar guid_buf[GUID_ENCODING_LENGTH+1];
+
+ memset( value, 0, sizeof( GValue ) );
+
+ if( table_row->gobj_param_name != NULL ) {
+ g_object_get( pObject, table_row->gobj_param_name, &guid, NULL );
+ } else {
+ getter = gnc_gda_get_getter( obj_name, table_row );
+ guid = (*getter)( pObject, NULL );
+ }
+ if( guid != NULL ) {
+ (void)guid_to_string_buff( guid, guid_buf );
+ g_value_init( value, G_TYPE_STRING );
+ g_value_set_string( value, guid_buf );
+ }
+}
+
+static void
+get_gvalue_guid_for_query( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_guid( be, obj_name, pObject, table_row, &value );
+ gnc_gda_add_field_to_query( query, table_row->col_name, &value );
+}
+
+static GdaQueryCondition*
+get_gvalue_guid_cond( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_guid( be, obj_name, pObject, table_row, &value );
+ return gnc_gda_create_condition_from_field( query, table_row->col_name, &value );
+}
+
+static void
+create_guid_col( GdaServerProvider* server, GdaConnection* cnn,
+ xmlNodePtr array_data, const col_cvt_t* table_row, gboolean pkey )
+{
+ gnc_gda_add_table_column( server, cnn, array_data, table_row->col_name,
+ "char", GUID_ENCODING_LENGTH, table_row->flags | pkey ? COL_PKEY : 0 );
+}
+
+static col_type_handler_t guid_handler =
+ { load_guid, create_guid_col,
+ get_gvalue_guid_for_query, get_gvalue_guid_cond };
+/* ----------------------------------------------------------------- */
+
+static void
+get_gvalue_objectref_guid( const GncGdaBackend* be, QofIdTypeConst obj_name, const gpointer pObject,
+ const col_cvt_t* table_row, GValue* value )
+{
+ QofAccessFunc getter;
+ const GUID* guid = NULL;
+ gchar guid_buf[GUID_ENCODING_LENGTH+1];
+ QofInstance* inst;
+
+ memset( value, 0, sizeof( GValue ) );
+
+ if( table_row->gobj_param_name != NULL ) {
+ g_object_get( pObject, table_row->gobj_param_name, &inst, NULL );
+ } else {
+ getter = gnc_gda_get_getter( obj_name, table_row );
+ inst = (*getter)( pObject, NULL );
+ }
+ if( inst != NULL ) {
+ guid = qof_instance_get_guid( inst );
+ }
+ if( guid != NULL ) {
+ (void)guid_to_string_buff( guid, guid_buf );
+ g_value_init( value, G_TYPE_STRING );
+ g_value_set_string( value, guid_buf );
+ }
+}
+
+void
+gnc_gda_get_gvalue_objectref_guid_for_query( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_objectref_guid( be, obj_name, pObject, table_row, &value );
+ gnc_gda_add_field_to_query( query, table_row->col_name, &value );
+}
+
+GdaQueryCondition*
+gnc_gda_get_gvalue_objectref_guid_cond( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_objectref_guid( be, obj_name, pObject, table_row, &value );
+ return gnc_gda_create_condition_from_field( query, table_row->col_name, &value );
+}
+
+void
+gnc_gda_create_objectref_guid_col( GdaServerProvider* server, GdaConnection* cnn,
+ xmlNodePtr array_data, const col_cvt_t* table_row, gboolean pkey )
+{
+ gnc_gda_add_table_column( server, cnn, array_data, table_row->col_name,
+ "char", GUID_ENCODING_LENGTH, table_row->flags | pkey ? COL_PKEY : 0 );
+}
+
+static void
+load_account_guid( const GncGdaBackend* be, GdaDataModel* pModel, gint row,
+ QofSetterFunc setter, gpointer pObject,
+ const col_cvt_t* table )
+{
+ const GValue* val;
+ GUID guid;
+ const GUID* pGuid;
+ Account* account = NULL;
+
+ 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;
+ }
+ if( pGuid != NULL ) {
+ account = xaccAccountLookup( pGuid, be->primary_book );
+ }
+ if( table->gobj_param_name != NULL ) {
+ g_object_set( pObject, table->gobj_param_name, account, NULL );
+ } else {
+ (*setter)( pObject, (const gpointer)account );
+ }
+}
+
+static col_type_handler_t account_guid_handler =
+ { load_account_guid, gnc_gda_create_objectref_guid_col,
+ gnc_gda_get_gvalue_objectref_guid_for_query, gnc_gda_get_gvalue_objectref_guid_cond };
+/* ----------------------------------------------------------------- */
+
+static void
+load_commodity_guid( const GncGdaBackend* be, GdaDataModel* pModel, gint row,
+ QofSetterFunc setter, gpointer pObject,
+ const col_cvt_t* table )
+{
+ const GValue* val;
+ GUID guid;
+ const GUID* pGuid;
+ gnc_commodity* commodity = NULL;
+
+ 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;
+ }
+ if( pGuid != NULL ) {
+ commodity = gnc_commodity_find_commodity_by_guid( pGuid, be->primary_book );
+ }
+ if( table->gobj_param_name != NULL ) {
+ g_object_set( pObject, table->gobj_param_name, commodity, NULL );
+ } else {
+ (*setter)( pObject, (const gpointer)commodity );
+ }
+}
+
+static col_type_handler_t commodity_guid_handler =
+ { load_commodity_guid, gnc_gda_create_objectref_guid_col,
+ gnc_gda_get_gvalue_objectref_guid_for_query, gnc_gda_get_gvalue_objectref_guid_cond };
+/* ----------------------------------------------------------------- */
+
+static void
+load_tx_guid( const GncGdaBackend* be, GdaDataModel* pModel, gint row,
+ QofSetterFunc setter, gpointer pObject,
+ const col_cvt_t* table )
+{
+ const GValue* val;
+ GUID guid;
+ const GUID* pGuid;
+ Transaction* tx = NULL;
+
+ 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;
+ }
+ if( pGuid != NULL ) {
+ tx = xaccTransLookup( pGuid, be->primary_book );
+ }
+ if( table->gobj_param_name != NULL ) {
+ g_object_set( pObject, table->gobj_param_name, tx, NULL );
+ } else {
+ (*setter)( pObject, (const gpointer)tx );
+ }
+}
+
+static col_type_handler_t tx_guid_handler =
+ { load_tx_guid, gnc_gda_create_objectref_guid_col,
+ gnc_gda_get_gvalue_objectref_guid_for_query, gnc_gda_get_gvalue_objectref_guid_cond };
+/* ----------------------------------------------------------------- */
+static void
+load_timespec( const GncGdaBackend* be, GdaDataModel* pModel, gint row,
+ QofSetterFunc setter, gpointer pObject,
+ const col_cvt_t* table )
+{
+ const GValue* val;
+ GDate* date;
+ Timespec ts;
+
+ val = gda_data_model_get_value_at_col_name( pModel, table->col_name, row );
+ if( gda_value_is_null( val ) ) {
+ (*setter)( pObject, NULL );
+ } else {
+ if( G_VALUE_HOLDS_STRING( val ) ) {
+ const gchar* s = g_value_get_string( val );
+ gchar* buf;
+ buf = g_strdup_printf( "%c%c%c%c-%c%c-%c%c 00:00:00",
+ s[6], s[7], s[8], s[9],
+ s[0], s[1],
+ s[3], s[4] );
+ ts = gnc_iso8601_to_timespec_gmt( buf );
+ (*setter)( pObject, &ts );
+ g_free( buf );
+
+ } else if( G_VALUE_HOLDS_BOXED( val ) ) {
+ date = (GDate*)g_value_get_boxed( val );
+ if( date != NULL ) {
+ ts = gnc_dmy2timespec( g_date_get_day( date ),
+ g_date_get_month( date ),
+ g_date_get_year( date ) );
+ (*setter)( pObject, &ts );
+ }
+ } else {
+ g_warning( "Unknown timespec type: %s", G_VALUE_TYPE_NAME( val ) );
+ }
+ }
+}
+
+static void
+get_gvalue_timespec( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GValue* value )
+{
+ QofAccessFunc getter;
+ Timespec* pTimespec;
+
+ memset( value, 0, sizeof( GValue ) );
+
+ getter = gnc_gda_get_getter( obj_name, table_row );
+ pTimespec = (Timespec*)(*getter)( pObject, NULL );
+ if( pTimespec != NULL ) {
+ GDate* date;
+ gint y, m, d;
+ gchar iso8601_buf[33];
+
+ date = g_date_new();
+ (void)gnc_timespec_to_iso8601_buff( *pTimespec, iso8601_buf );
+ sscanf( iso8601_buf, "%d-%d-%d", &y, &m, &d );
+ g_date_set_dmy( date, d, m, y );
+ g_value_init( value, G_TYPE_DATE );
+ g_value_set_boxed( value, date );
+ }
+}
+
+static void
+get_gvalue_timespec_for_query( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_timespec( be, obj_name, pObject, table_row, &value );
+ gnc_gda_add_field_to_query( query, table_row->col_name, &value );
+}
+
+static GdaQueryCondition*
+get_gvalue_timespec_cond( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_timespec( be, obj_name, pObject, table_row, &value );
+ return gnc_gda_create_condition_from_field( query, table_row->col_name, &value );
+}
+
+static void
+create_timespec_col( GdaServerProvider* server, GdaConnection* cnn,
+ xmlNodePtr array_data, const col_cvt_t* table_row, gboolean pkey )
+{
+ const gchar* dbms_type;
+
+ dbms_type = gda_server_provider_get_default_dbms_type( server,
+ cnn, G_TYPE_DATE );
+ gnc_gda_add_table_column( server, cnn, array_data, table_row->col_name,
+ dbms_type, table_row->size, table_row->flags | pkey ? COL_PKEY : 0 );
+}
+
+static col_type_handler_t timespec_handler =
+ { load_timespec, create_timespec_col,
+ get_gvalue_timespec_for_query, get_gvalue_timespec_cond };
+/* ----------------------------------------------------------------- */
+static void
+load_date( const GncGdaBackend* be, GdaDataModel* pModel, gint row,
+ QofSetterFunc setter, gpointer pObject,
+ const col_cvt_t* table )
+{
+ const GValue* val;
+ GDate* date;
+
+ val = gda_data_model_get_value_at_col_name( pModel, table->col_name, row );
+ if( gda_value_is_null( val ) ) {
+ date = g_date_new_dmy( 1, 1, 1970 );
+ (*setter)( pObject, date );
+ g_date_free( date );
+ } else {
+ if( G_VALUE_HOLDS_STRING( val ) ) {
+ const gchar* s = g_value_get_string( val );
+ guint year = atoi( &s[6] );
+ guint month = atoi( &s[0] );
+ guint day = atoi( &s[3] );
+
+ date = g_date_new_dmy( day, month, year );
+ (*setter)( pObject, date );
+ g_date_free( date );
+
+ } else if( G_VALUE_HOLDS_BOXED( val ) ) {
+ date = (GDate*)g_value_get_boxed( val );
+ if( date != NULL ) {
+ (*setter)( pObject, date );
+ g_date_free( date );
+ }
+ } else {
+ g_warning( "Unknown timespec type: %s", G_VALUE_TYPE_NAME( val ) );
+ }
+ }
+}
+
+static void
+get_gvalue_date( const GncGdaBackend* be, QofIdTypeConst obj_name, const gpointer pObject,
+ const col_cvt_t* table_row, GValue* value )
+{
+ GDate* date;
+ QofAccessFunc getter;
+
+ memset( value, 0, sizeof( GValue ) );
+
+ getter = gnc_gda_get_getter( obj_name, table_row );
+ date = (GDate*)(*getter)( pObject, NULL );
+ if( date != NULL ) {
+ g_value_init( value, G_TYPE_DATE );
+ g_value_set_boxed( value, date );
+ }
+}
+
+static void
+get_gvalue_date_for_query( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_date( be, obj_name, pObject, table_row, &value );
+ gnc_gda_add_field_to_query( query, table_row->col_name, &value );
+}
+
+static GdaQueryCondition*
+get_gvalue_date_cond( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+
+ get_gvalue_date( be, obj_name, pObject, table_row, &value );
+ return gnc_gda_create_condition_from_field( query, table_row->col_name, &value );
+}
+
+static col_type_handler_t date_handler =
+ { load_date, create_timespec_col,
+ get_gvalue_date_for_query, get_gvalue_date_cond };
+/* ----------------------------------------------------------------- */
+static gint64
+get_integer_value( const GValue* value )
+{
+ if( G_VALUE_HOLDS_INT(value) ) {
+ return g_value_get_int( value );
+ } else if( G_VALUE_HOLDS_UINT(value) ) {
+ return g_value_get_uint( value );
+ } else if( G_VALUE_HOLDS_LONG(value) ) {
+ return g_value_get_long( value );
+ } else if( G_VALUE_HOLDS_ULONG(value) ) {
+ return g_value_get_ulong( value );
+ } else if( G_VALUE_HOLDS_INT64(value) ) {
+ return g_value_get_int64( value );
+ } else if( G_VALUE_HOLDS_UINT64(value) ) {
+ return g_value_get_uint64( value );
+ } else {
+ g_warning( "Unknown type: %s", G_VALUE_TYPE_NAME( value ) );
+ }
+
+ return 0;
+}
+
+typedef void (*NumericSetterFunc)( gpointer, gnc_numeric );
+typedef gnc_numeric (*NumericGetterFunc)( const gpointer );
+
+static void
+load_numeric( const GncGdaBackend* be, GdaDataModel* pModel, gint row,
+ QofSetterFunc setter, gpointer pObject,
+ const col_cvt_t* table )
+{
+ const GValue* val;
+ gchar* buf;
+ gint64 num, denom;
+ gnc_numeric n;
+ gboolean isNull = FALSE;
+ NumericSetterFunc n_setter = (NumericSetterFunc)setter;
+
+ buf = g_strdup_printf( "%s_num", table->col_name );
+ val = gda_data_model_get_value_at_col_name( pModel, buf, row );
+ g_free( buf );
+ if( gda_value_is_null( val ) ) {
+ isNull = TRUE;
+ num = 0;
+ } else {
+ num = get_integer_value( 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 );
+ if( gda_value_is_null( val ) ) {
+ isNull = TRUE;
+ denom = 1;
+ } else {
+ denom = get_integer_value( val );
+ }
+ n = gnc_numeric_create( num, denom );
+ if( !isNull ) {
+ (*n_setter)( pObject, n );
+ }
+}
+
+static void
+get_gvalue_numeric( const GncGdaBackend* be, QofIdTypeConst obj_name, const gpointer pObject,
+ const col_cvt_t* table_row, GValue* value )
+{
+ NumericGetterFunc getter;
+ gnc_numeric n;
+
+ memset( value, 0, sizeof( GValue ) );
+
+ getter = (NumericGetterFunc)gnc_gda_get_getter( obj_name, table_row );
+ n = (*getter)( pObject );
+ g_value_init( value, gnc_numeric_get_type() );
+ g_value_set_boxed( value, &n );
+}
+
+static void
+get_gvalue_numeric_for_query( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+ GValue num_value;
+ GValue denom_value;
+ gnc_numeric* n;
+ gchar* s;
+
+ memset( &value, 0, sizeof( GValue ) );
+ memset( &num_value, 0, sizeof( GValue ) );
+ memset( &denom_value, 0, sizeof( GValue ) );
+
+ get_gvalue_numeric( be, obj_name, pObject, table_row, &value );
+ if( G_VALUE_TYPE(&value) != 0 ) {
+ n = g_value_get_boxed( &value );
+ g_value_init( &num_value, G_TYPE_INT64 );
+ g_value_set_int64( &num_value, gnc_numeric_num( *n ) );
+ g_value_init( &denom_value, G_TYPE_INT64 );
+ g_value_set_int64( &denom_value, gnc_numeric_denom( *n ) );
+ }
+
+ s = g_strdup_printf( "%s_num", table_row->col_name );
+ gnc_gda_add_field_to_query( query, s, &num_value );
+ g_free( s );
+ s = g_strdup_printf( "%s_denom", table_row->col_name );
+ gnc_gda_add_field_to_query( query, s, &denom_value );
+ g_free( s );
+}
+
+static GdaQueryCondition*
+get_gvalue_numeric_cond( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+ GValue num_value;
+ GValue denom_value;
+ gnc_numeric* n;
+ gchar* s;
+ GdaQueryCondition* num_cond;
+ GdaQueryCondition* denom_cond;
+ GdaQueryCondition* cond;
+
+ memset( &value, 0, sizeof( GValue ) );
+ memset( &num_value, 0, sizeof( GValue ) );
+ memset( &denom_value, 0, sizeof( GValue ) );
+
+ get_gvalue_numeric( be, obj_name, pObject, table_row, &value );
+ if( G_VALUE_TYPE(&value) != 0 ) {
+ n = g_value_get_boxed( &value );
+ g_value_init( &num_value, G_TYPE_INT64 );
+ g_value_set_int64( &num_value, gnc_numeric_num( *n ) );
+ g_value_init( &denom_value, G_TYPE_INT64 );
+ g_value_set_int64( &denom_value, gnc_numeric_denom( *n ) );
+ }
+
+ s = g_strdup_printf( "%s_num", table_row->col_name );
+ num_cond = gnc_gda_create_condition_from_field( query, s, &value );
+ g_free( s );
+ s = g_strdup_printf( "%s_denom", table_row->col_name );
+ denom_cond = gnc_gda_create_condition_from_field( query, s, &value );
+ g_free( s );
+
+ cond = gda_query_condition_new( query, GDA_QUERY_CONDITION_NODE_AND );
+ gda_query_condition_node_add_child( cond, num_cond, NULL );
+ gda_query_condition_node_add_child( cond, denom_cond, NULL );
+
+ return cond;
+}
+
+static void
+create_numeric_col( GdaServerProvider* server, GdaConnection* cnn,
+ xmlNodePtr array_data, const col_cvt_t* table_row, gboolean pkey )
+{
+ 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 );
+ gnc_gda_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 );
+ gnc_gda_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, create_numeric_col,
+ get_gvalue_numeric_for_query, get_gvalue_numeric_cond };
+/* ================================================================= */
+
+static GHashTable* g_columnTypeHash = NULL;
+
+void
+gnc_gda_register_col_type_handler( const gchar* colType, const col_type_handler_t* handler )
+{
+ if( g_columnTypeHash == NULL ) {
+ g_columnTypeHash = g_hash_table_new( g_str_hash, g_str_equal );
+ }
+
+ g_hash_table_insert( g_columnTypeHash, (gpointer)colType, (gpointer)handler );
+}
+
+static col_type_handler_t*
+get_handler( const gchar* col_type )
+{
+ col_type_handler_t* pHandler;
+
+ pHandler = g_hash_table_lookup( g_columnTypeHash, col_type );
+ if( pHandler == NULL ) {
+ g_assert( FALSE );
+ }
+
+ return pHandler;
+}
+
+void
+gnc_gda_register_standard_col_type_handlers( void )
+{
+ gnc_gda_register_col_type_handler( CT_STRING, &string_handler );
+ gnc_gda_register_col_type_handler( CT_BOOLEAN, &boolean_handler );
+ gnc_gda_register_col_type_handler( CT_INT, &int_handler );
+ gnc_gda_register_col_type_handler( CT_INT64, &int64_handler );
+ gnc_gda_register_col_type_handler( CT_DOUBLE, &double_handler );
+ gnc_gda_register_col_type_handler( CT_GUID, &guid_handler );
+ gnc_gda_register_col_type_handler( CT_ACCOUNTREF, &account_guid_handler );
+ gnc_gda_register_col_type_handler( CT_COMMODITYREF, &commodity_guid_handler );
+ gnc_gda_register_col_type_handler( CT_TXREF, &tx_guid_handler );
+ gnc_gda_register_col_type_handler( CT_TIMESPEC, ×pec_handler );
+ gnc_gda_register_col_type_handler( CT_GDATE, &date_handler );
+ gnc_gda_register_col_type_handler( CT_NUMERIC, &numeric_handler );
+}
+
+static void retrieve_guid( gpointer pObject, gpointer pValue );
+
+static void
+retrieve_guid( gpointer pObject, gpointer pValue )
+{
+ GUID* pGuid = (GUID*)pObject;
+ GUID* guid = (GUID*)pValue;
+
+ memcpy( pGuid, guid, sizeof( GUID ) );
+}
+
+
+// Table to retrieve just the guid
+static col_cvt_t guid_table[] =
+{
+ { "guid", CT_GUID, 0, 0, NULL, NULL, NULL, retrieve_guid },
+ { NULL }
+};
+
+const GUID*
+gnc_gda_load_guid( const GncGdaBackend* be, GdaDataModel* pModel, gint row )
+{
+ static GUID guid;
+
+ gnc_gda_load_object( be, pModel, row, NULL, &guid, guid_table );
+
+ return &guid;
+}
+
+// Table to retrieve just the guid
+static col_cvt_t tx_guid_table[] =
+{
+ { "tx_guid", CT_GUID, 0, 0, NULL, NULL, NULL, retrieve_guid },
+ { NULL }
+};
+
+const GUID*
+gnc_gda_load_tx_guid( const GncGdaBackend* be, GdaDataModel* pModel, gint row )
+{
+ static GUID guid;
+
+ gnc_gda_load_object( be, pModel, row, NULL, &guid, tx_guid_table );
+
+ return &guid;
+}
+
+void
+gnc_gda_load_object( const GncGdaBackend* be, 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( be, pModel, row, setter, pObject, &table[col] );
+ }
+}
+
+/* ================================================================= */
+GdaQuery*
+gnc_gda_create_select_query( const GncGdaBackend* be, const gchar* table_name )
+{
+ GdaQuery* query;
+ GdaQueryTarget* target;
+ GdaQueryField* allFields;
+
+ /* SELECT */
+ query = gda_query_new( be->pDict );
+ gda_query_set_query_type( query, GDA_QUERY_TYPE_SELECT );
+
+ /* FROM */
+ target = gda_query_target_new( query, table_name );
+ gda_query_add_target( query, target, NULL );
+ g_object_unref( G_OBJECT(target) );
+
+ /* all fields */
+ allFields = gda_query_field_all_new( query, table_name );
+ gda_query_field_set_visible( allFields, TRUE );
+ gda_entity_add_field( GDA_ENTITY(query), GDA_ENTITY_FIELD(allFields) );
+ g_object_unref( G_OBJECT(allFields) );
+
+ return query;
+}
+
+/* ================================================================= */
+GdaObject*
+gnc_gda_execute_query( const GncGdaBackend* be, GdaQuery* query )
+{
+ GError* error = NULL;
+
+ GdaObject* ret;
+
+ ret = gda_query_execute( query, NULL, FALSE, &error );
+
+ if( error != NULL ) {
+ g_critical( "SQL error: %s\n", error->message );
+ }
+
+ return ret;
+}
+
+GdaQuery*
+gnc_gda_create_query_from_sql( const GncGdaBackend* be, const gchar* sql )
+{
+ GError* error = NULL;
+
+ GdaQuery* query;
+
+ query = gda_query_new_from_sql( be->pDict, sql, &error );
+ if( query == NULL ) {
+ g_critical( "SQL error: %s\n", error->message );
+ }
+
+ return query;
+}
+
+GdaObject*
+gnc_gda_execute_sql( const GncGdaBackend* be, const gchar* sql )
+{
+ GdaQuery* query;
+
+ query = gnc_gda_create_query_from_sql( be, sql );
+ if( query != NULL ) {
+ return gnc_gda_execute_query( be, query );
+ } else {
+ return NULL;
+ }
+}
+
+int
+gnc_gda_execute_select_get_count( const 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 = GDA_DATA_MODEL(ret);
+ count = gda_data_model_get_n_rows( pModel );
+ }
+
+ if( error != NULL ) {
+ g_critical( "SQL error: %s\n", error->message );
+ }
+
+ return count;
+}
+
+int
+gnc_gda_execute_query_get_count( const GncGdaBackend* be, GdaQuery* query )
+{
+ int count = 0;
+
+ GdaObject* ret;
+
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL(ret) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ count = gda_data_model_get_n_rows( pModel );
+ }
+
+ return count;
+}
+/* ================================================================= */
+static void
+get_col_gvalue_for_query( GncGdaBackend* be, QofIdTypeConst obj_name,
+ gpointer pObject, const col_cvt_t* table_row,
+ GdaQuery* query )
+{
+ col_type_handler_t* pHandler;
+
+ pHandler = get_handler( table_row->col_type );
+ pHandler->get_gvalue_query_fn( be, obj_name, pObject, table_row, query );
+}
+
+static void
+get_col_gvalue_for_condition( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ gpointer pObject, const col_cvt_t* table_row,
+ GdaQuery* query )
+{
+ col_type_handler_t* pHandler;
+ GdaQueryCondition* cond;
+
+ pHandler = get_handler( table_row->col_type );
+ cond = pHandler->get_gvalue_cond_fn( be, obj_name, pObject, table_row, query );
+
+ gda_query_set_condition( query, cond );
+ g_object_unref( G_OBJECT(cond) );
+}
+
+gboolean
+gnc_gda_object_is_it_in_db( const GncGdaBackend* be, const gchar* table_name,
+ QofIdTypeConst obj_name, gpointer pObject,
+ const col_cvt_t* table )
+{
+ GdaQuery* query;
+ int count;
+
+ /* SELECT * FROM */
+ query = gnc_gda_create_select_query( be, table_name );
+
+ /* WHERE */
+ get_col_gvalue_for_condition( be, obj_name, pObject, &table[0], query );
+
+ count = gnc_gda_execute_query_get_count( be, query );
+ if( count == 0 ) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+gboolean
+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( gnc_gda_object_is_it_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, obj_name, pObject, table );
+ }
+ } else if( op == OP_DB_DELETE ) {
+ pQuery = gnc_gda_build_delete_query( be, table_name, obj_name, pObject, table );
+ } else if( op == OP_DB_ADD ) {
+ pQuery = gnc_gda_build_insert_query( be, table_name, obj_name, pObject, 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;
+ }
+}
+
+#define INITIAL_SQL_BUF_LEN 500
+
+GdaQuery*
+gnc_gda_build_insert_query( GncGdaBackend* be,
+ const gchar* table_name,
+ QofIdTypeConst obj_name, gpointer pObject,
+ const col_cvt_t* table )
+{
+ GdaQuery* query;
+ int col;
+
+ GdaQueryTarget* target;
+
+ /* INSERT */
+ query = gda_query_new( be->pDict );
+ gda_query_set_query_type( query, GDA_QUERY_TYPE_INSERT );
+
+ /* INTO */
+ target = gda_query_target_new( query, table_name );
+ gda_query_add_target( query, target, NULL );
+
+ /* VALUES */
+ for( col = 0; table[col].col_name != NULL; col++ ) {
+ if(( table[col].flags & COL_AUTOINC ) == 0 ) {
+ get_col_gvalue_for_query( be, obj_name, pObject, &table[col], query );
+ }
+ }
+
+ return query;
+}
+
+GdaQuery*
+gnc_gda_build_update_query( GncGdaBackend* be,
+ const gchar* table_name,
+ QofIdTypeConst obj_name, gpointer pObject,
+ const col_cvt_t* table )
+{
+ GdaQuery* query;
+ int col;
+
+ GdaQueryTarget* target;
+
+ /* UPDATE */
+ query = gda_query_new( be->pDict );
+ gda_query_set_query_type( query, GDA_QUERY_TYPE_UPDATE );
+ target = gda_query_target_new( query, table_name );
+ gda_query_add_target( query, target, NULL );
+
+ /* SET */
+ for( col = 1; table[col].col_name != NULL; col++ ) {
+ get_col_gvalue_for_query( be, obj_name, pObject, &table[col], query );
+ }
+
+ /* WHERE */
+ get_col_gvalue_for_condition( be, obj_name, pObject, &table[0], query );
+
+ return query;
+}
+
+GdaQuery*
+gnc_gda_build_delete_query( GncGdaBackend* be,
+ const gchar* table_name,
+ QofIdTypeConst obj_name, gpointer pObject,
+ const col_cvt_t* table )
+{
+ GdaQuery* query;
+ GdaQueryTarget* target;
+
+ /* DELETE */
+ query = gda_query_new( be->pDict );
+ gda_query_set_query_type( query, GDA_QUERY_TYPE_DELETE );
+
+ /* FROM */
+ target = gda_query_target_new( query, table_name );
+ gda_query_add_target( query, target, NULL );
+ g_object_unref( G_OBJECT(target) );
+
+ /* WHERE */
+ get_col_gvalue_for_condition( be, obj_name, pObject, &table[0], query );
+
+ return query;
+}
+
+/* ================================================================= */
+void
+gnc_gda_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,
+ const 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;
+
+ 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++ ) {
+ col_type_handler_t* pHandler;
+
+ pHandler = get_handler( col_table[col].col_type );
+
+ pHandler->create_col_fn( server, cnn, array_data, &col_table[col], col == 0 );
+ }
+
+ 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;
+}
+
+void gnc_gda_create_table_if_needed( const GncGdaBackend* be,
+ const gchar* table_name,
+ const col_cvt_t* col_table )
+{
+ 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 );
+ if( error != NULL ) {
+ g_critical( "Error creating table: %s\n", error->message );
+ }
+ }
+}
+/* ================================================================= */
+#if 0
+static gboolean
+create_or_drop_db( GdaConnection* cnn, GdaServerOperationType opType,
+ const gchar* db_name, GError** error )
+{
+ typedef struct {
+ GdaServerOperationType opType;
+ const gchar* op_name;
+ const gchar* op_path_name;
+ } S_ServerOpInfo;
+#define NUMOF(X) (sizeof(X)/sizeof(X[0]))
+ static S_ServerOpInfo s_op_info[] =
+ {
+ { GDA_SERVER_OPERATION_CREATE_DB, "CREATE DB", "DB_DEF_P" },
+ { GDA_SERVER_OPERATION_DROP_DB, "DROP DB", "DB_DESC_P" }
+ };
+#define NUM_OPS NUMOF(s_op_info)
+ S_ServerOpInfo* op_info;
+ GdaServerOperation *op;
+ GdaServerProvider *server;
+ gchar* buf;
+ gint i;
+
+ g_return_val_if_fail( GDA_IS_CONNECTION(cnn), FALSE );
+ g_return_val_if_fail( gda_connection_is_opened(cnn), FALSE );
+
+ if( db_name == NULL ) {
+ g_message( "Database name is NULL!" );
+ g_set_error( error,
+ GDA_GENERAL_ERROR, GDA_GENERAL_OBJECT_NAME_ERROR,
+ "Couldn't create or drop database with a NULL string" );
+ return FALSE;
+ }
+
+ for( i = 0, op_info = NULL; i < NUM_OPS; i++ ) {
+ if( s_op_info[i].opType == opType ) {
+ op_info = &s_op_info[i];
+ break;
+ }
+ }
+
+ g_return_val_if_fail( op_info != NULL, FALSE );
+
+ server = gda_connection_get_provider_obj( cnn );
+ op = gda_server_provider_create_operation( server, cnn, opType, NULL,
+ error );
+ if( GDA_IS_SERVER_OPERATION(op) ) {
+ xmlDocPtr parameters;
+ xmlNodePtr root;
+ xmlNodePtr db;
+
+ /* Initation of the xmlDoc */
+ parameters = xmlNewDoc( "1.0" );
+
+ root = xmlNewDocNode( parameters, NULL, "serv_op_data", NULL );
+ xmlDocSetRootElement( parameters, root );
+ db = xmlNewChild( root, NULL, "op_data", db_name );
+ buf = g_strdup_printf( "/%s/DB_NAME", op_info->op_path_name );
+ xmlSetProp( db, "path", buf );
+ g_free( buf );
+
+ 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 */
+ buf = g_strdup_printf( "The server couldn't perform the %s operation",
+ op_info->op_name );
+ g_set_error( error,
+ GDA_GENERAL_ERROR, GDA_GENERAL_OPERATION_ERROR,
+ buf );
+ g_free( buf );
+ g_object_unref( op );
+ xmlFreeDoc( parameters );
+ return FALSE;
+ }
+ }
+
+ g_object_unref( op );
+ xmlFreeDoc( parameters );
+ } else {
+ buf = g_strdup_printf( "The server doesn't support the %s operation",
+ op_info->op_name );
+ g_set_error( error, GDA_GENERAL_ERROR, GDA_GENERAL_OBJECT_NAME_ERROR,
+ buf );
+ g_free( buf );
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+drop_db( GncGdaBackend* be, const gchar* db_name, GError** error )
+{
+ return create_or_drop_db( be->pConnection, GDA_SERVER_OPERATION_DROP_DB,
+ db_name, error );
+}
+
+static gboolean
+create_db( GncGdaBackend* be, const gchar* db_name, GError** error )
+{
+ return create_or_drop_db( be->pConnection, GDA_SERVER_OPERATION_CREATE_DB,
+ db_name, error );
+}
+#endif
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-util-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-util-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-backend-util-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,191 @@
+/********************************************************************
+ * gnc-backend-gda.h: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-backend-gda.h
+ * @brief load and save data to SQL via libgda
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_BACKEND_GDA_UTIL_H_
+#define GNC_BACKEND_GDA_UTIL_H_
+
+#include "qof.h"
+#include <gmodule.h>
+
+#include "qofbackend-p.h"
+struct GncGdaBackend_struct
+{
+ QofBackend be;
+
+ GdaClient* pClient;
+ GdaConnection* pConnection;
+ GdaDict* pDict;
+
+ QofBook *primary_book; /* The primary, main open book */
+ gboolean loading; /* We are performing an initial load */
+ gboolean in_query;
+};
+typedef struct GncGdaBackend_struct GncGdaBackend;
+
+/**
+ * Struct used to pass in a new data type for GDA storage. This contains
+ * the set of callbacks to read and write GDA for new data objects.. New
+ * types should register an instance of this object with the engine.
+ *
+ * commit() - commit an object to the db
+ * initial_load() - load stuff when new db opened
+ */
+#define GNC_GDA_BACKEND "gnc:gda:1"
+#define GNC_GDA_BACKEND_VERSION 1
+typedef struct
+{
+ int version; /* backend version number */
+ const gchar * type_name; /* The XML tag for this type */
+
+ void (*commit)( GncGdaBackend* pBackend, QofInstance* inst );
+ void (*initial_load)( GncGdaBackend* pBackend );
+ void (*create_tables)( GncGdaBackend* pBackend );
+ gpointer (*compile_query)( GncGdaBackend* pBackend, QofQuery* pQuery );
+ void (*run_query)( GncGdaBackend* pBackend, gpointer pQuery );
+ void (*free_query)( GncGdaBackend* pBackend, gpointer pQuery );
+} GncGdaDataType_t;
+
+// Type for conversion of db row to object.
+#define CT_STRING "ct_string"
+#define CT_GUID "ct_guid"
+#define CT_INT "ct_int"
+#define CT_INT64 "ct_int64"
+#define CT_TIMESPEC "ct_timespec"
+#define CT_GDATE "ct_gdate"
+#define CT_NUMERIC "ct_numeric"
+#define CT_DOUBLE "ct_double"
+#define CT_BOOLEAN "ct_boolean"
+#define CT_ACCOUNTREF "ct_accountref"
+#define CT_COMMODITYREF "ct_commodityref"
+#define CT_TXREF "ct_txref"
+
+typedef struct {
+ const gchar* col_name;
+ const gchar* col_type;
+ gint size;
+#define COL_PKEY 0x01
+#define COL_NNUL 0x02
+#define COL_UNIQUE 0x04
+#define COL_AUTOINC 0x08
+ gint flags;
+ const gchar* gobj_param_name; // If non-null, use g_object_get/g_object_set
+ const gchar* param_name; // If non null, use qof getter/setter
+ QofAccessFunc getter;
+ QofSetterFunc setter;
+} col_cvt_t;
+
+typedef enum {
+ OP_DB_ADD,
+ OP_DB_ADD_OR_UPDATE,
+ OP_DB_DELETE
+} E_DB_OPERATION;
+
+typedef void (*GNC_GDA_LOAD_FN)( const GncGdaBackend* be, GdaDataModel* pModel, gint row,
+ QofSetterFunc setter, gpointer pObject,
+ const col_cvt_t* table );
+typedef void (*GNC_GDA_CREATE_COL_FN)( GdaServerProvider* server,
+ GdaConnection* cnn, xmlNodePtr array_data,
+ const col_cvt_t* table_row, gboolean pkey );
+typedef void (*GNC_GDA_GET_GVALUE_QUERY_FN)( const GncGdaBackend* be,
+ QofIdTypeConst obj_name, const gpointer pObject,
+ const col_cvt_t* table_row, GdaQuery* query );
+typedef GdaQueryCondition* (*GNC_GDA_GET_GVALUE_COND_FN)( const GncGdaBackend* be,
+ QofIdTypeConst obj_name, const gpointer pObject,
+ const col_cvt_t* table_row, GdaQuery* query );
+
+typedef struct {
+ GNC_GDA_LOAD_FN load_fn;
+ GNC_GDA_CREATE_COL_FN create_col_fn;
+ GNC_GDA_GET_GVALUE_QUERY_FN get_gvalue_query_fn;
+ GNC_GDA_GET_GVALUE_COND_FN get_gvalue_cond_fn;
+} col_type_handler_t;
+
+QofAccessFunc gnc_gda_get_getter( QofIdTypeConst obj_name, const col_cvt_t* table_row );
+void gnc_gda_add_table_column( GdaServerProvider* server, GdaConnection* cnn,
+ xmlNodePtr array_data, const gchar* arg, const gchar* dbms_type,
+ gint size, gint flags );
+
+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( const GncGdaBackend* pBackend, GdaQuery* pQuery );
+GdaObject* gnc_gda_execute_sql( const GncGdaBackend* pBackend, const gchar* sql );
+GdaQuery* gnc_gda_create_query_from_sql( const GncGdaBackend* pBackend, const gchar* sql );
+int gnc_gda_execute_select_get_count( const GncGdaBackend* pBackend, const gchar* sql );
+int gnc_gda_execute_query_get_count( const GncGdaBackend* pBackend, GdaQuery* query );
+void gnc_gda_load_object( const GncGdaBackend* be, GdaDataModel* pModel, int row,
+ QofIdTypeConst obj_name, gpointer pObject,
+ const col_cvt_t* table );
+gboolean gnc_gda_object_is_it_in_db( const GncGdaBackend* be,
+ const gchar* table_name,
+ QofIdTypeConst obj_name, const gpointer pObject,
+ const col_cvt_t* table );
+gboolean gnc_gda_create_table( GdaConnection* pConnection,
+ const gchar* table_name, const col_cvt_t* col_table,
+ GError** error );
+void gnc_gda_create_table_if_needed( const GncGdaBackend* be,
+ const gchar* table_name, const col_cvt_t* col_table );
+const GUID* gnc_gda_load_guid( const GncGdaBackend* be, GdaDataModel* pModel, int row );
+const GUID* gnc_gda_load_tx_guid( const GncGdaBackend* be, GdaDataModel* pModel, int row );
+GdaQuery* gnc_gda_create_select_query( const GncGdaBackend* be, const gchar* table_name );
+GdaQueryCondition* gnc_gda_create_condition_from_field( GdaQuery* query,
+ const gchar* col_name,
+ const GValue* value );
+void gnc_gda_register_col_type_handler( const gchar* colType, const col_type_handler_t* handler );
+void gnc_gda_register_standard_col_type_handlers( void );
+void gnc_gda_add_field_to_query( GdaQuery* query, const gchar* col_name, const GValue* value );
+
+void gnc_gda_get_gvalue_objectref_guid_for_query( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query );
+GdaQueryCondition* gnc_gda_get_gvalue_objectref_guid_cond( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query );
+void gnc_gda_create_objectref_guid_col( GdaServerProvider* server, GdaConnection* cnn,
+ xmlNodePtr array_data, const col_cvt_t* table_row, gboolean pkey );
+
+G_MODULE_EXPORT const gchar *
+g_module_check_init( GModule *module );
+
+#endif /* GNC_BACKEND_GDA_UTIL_H_ */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-book-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-book-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-book-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,207 @@
+/********************************************************************
+ * gnc-book-gda.c: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-book-gda.c
+ * @brief load and save data to SQL
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL db using libgda
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <libgda/libgda.h>
+
+#include "qof.h"
+
+#include "gnc-backend-util-gda.h"
+
+#include "gnc-book-gda.h"
+#include "gnc-slots-gda.h"
+
+#include "gnc-engine.h"
+#include "gnc-book.h"
+#include "SX-book.h"
+#include "SX-book-p.h"
+
+#define BOOK_TABLE "books"
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+static void commit_book( GncGdaBackend* be, QofInstance* inst );
+
+static gpointer get_root_account_guid( gpointer pObject, const QofParam* );
+static void set_root_account_guid( gpointer pObject, gpointer pValue );
+static gpointer get_root_template_guid( gpointer pObject, const QofParam* );
+static void set_root_template_guid( gpointer pObject, gpointer pValue );
+
+static col_cvt_t col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "root_account_guid", CT_GUID, 0, COL_NNUL, NULL, NULL, get_root_account_guid, set_root_account_guid },
+ { "root_template_guid", CT_GUID, 0, COL_NNUL, NULL, NULL, get_root_template_guid, set_root_template_guid },
+ { NULL }
+};
+
+/* ================================================================= */
+static gpointer
+get_root_account_guid( gpointer pObject, const QofParam* param )
+{
+ GNCBook* book = QOF_BOOK(pObject);
+ const Account* root = gnc_book_get_root_account( book );
+
+ return (gpointer)qof_instance_get_guid( QOF_INSTANCE( root ) );
+}
+
+static void
+set_root_account_guid( gpointer pObject, gpointer pValue )
+{
+ GNCBook* book = QOF_BOOK(pObject);
+ const Account* root = gnc_book_get_root_account( book );
+ GUID* guid = (GUID*)pValue;
+
+ qof_instance_set_guid( QOF_INSTANCE( root ), guid );
+}
+
+static gpointer
+get_root_template_guid( gpointer pObject, const QofParam* param )
+{
+ const GNCBook* book = QOF_BOOK(pObject);
+ const Account* root = gnc_book_get_template_root( book );
+
+ return (gpointer)qof_instance_get_guid( QOF_INSTANCE( root ) );
+}
+
+static void
+set_root_template_guid( gpointer pObject, gpointer pValue )
+{
+ GNCBook* book = QOF_BOOK(pObject);
+ GUID* guid = (GUID*)pValue;
+ Account* root = gnc_book_get_template_root( book );
+
+ if( root == NULL ) {
+ root = xaccMallocAccount( book );
+ xaccAccountBeginEdit( root );
+ xaccAccountSetType( root, ACCT_TYPE_ROOT );
+ xaccAccountCommitEdit( root );
+ gnc_book_set_template_root( book, root );
+ }
+ qof_instance_set_guid( QOF_INSTANCE( root ), guid );
+}
+
+/* ================================================================= */
+static GNCBook*
+load_single_book( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ const GUID* guid;
+ GUID book_guid;
+ GNCBook* pBook;
+
+ guid = gnc_gda_load_guid( be, pModel, row );
+ book_guid = *guid;
+
+ pBook = be->primary_book;
+ if( pBook == NULL ) {
+ pBook = gnc_book_new();
+ }
+
+ gnc_gda_load_object( be, pModel, row, GNC_ID_BOOK, pBook, col_table );
+ gnc_gda_slots_load( be, gnc_book_get_guid( pBook ),
+ qof_instance_get_slots( QOF_INSTANCE(pBook) ) );
+
+ qof_instance_mark_clean( QOF_INSTANCE(pBook) );
+
+ return pBook;
+}
+
+static void
+load_all_books( GncGdaBackend* be )
+{
+ static GdaQuery* query;
+ GdaObject* ret;
+ QofBook* pBook = be->primary_book;
+
+ if( query == NULL ) {
+ query = gnc_gda_create_select_query( be, BOOK_TABLE );
+ }
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+
+ // If there are no rows, try committing the book
+ if( numRows == 0 ) {
+ commit_book( be, QOF_INSTANCE( be->primary_book ) );
+ } else {
+ // Otherwise, load the 1st book.
+ (void)load_single_book( be, pModel, 0 );
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_book_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, BOOK_TABLE, col_table );
+}
+
+/* ================================================================= */
+static void
+commit_book( GncGdaBackend* be, QofInstance* inst )
+{
+ GNCBook* pBook = QOF_BOOK(inst);
+ const GUID* guid;
+
+ (void)gnc_gda_do_db_operation( be,
+ qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE,
+ BOOK_TABLE,
+ GNC_ID_BOOK, pBook,
+ col_table );
+
+ // Delete old slot info
+ guid = qof_instance_get_guid( inst );
+
+ // Now, commit any slots
+ if( !qof_instance_get_destroying(inst) ) {
+ gnc_gda_slots_save( be, guid, qof_instance_get_slots( inst ) );
+ } else {
+ gnc_gda_slots_delete( be, guid );
+ }
+}
+
+/* ================================================================= */
+void
+gnc_gda_init_book_handler( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_BOOK,
+ commit_book, /* commit */
+ load_all_books, /* initial_load */
+ create_book_tables /* create_tables */
+ };
+
+ qof_object_register_backend( GNC_ID_BOOK, GNC_GDA_BACKEND, &be_data );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-book-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-book-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-book-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,37 @@
+/********************************************************************
+ * gnc-book-gda.h: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-book-gda.h
+ * @brief load and save data to SQL via libgda
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_BOOK_GDA_H_
+#define GNC_BOOK_GDA_H_
+
+#include "qof.h"
+#include <gmodule.h>
+
+void gnc_gda_init_book_handler( void );
+
+#endif /* GNC_BOOK_GDA_H_ */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-budget-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-budget-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-budget-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,158 @@
+/********************************************************************
+ * gnc-budget-gda.c: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-budget-gda.c
+ * @brief load and save data to SQL
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL db using libgda
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <libgda/libgda.h>
+
+#include "qof.h"
+
+#include "gnc-backend-util-gda.h"
+
+#include "Recurrence.h"
+
+#include "gnc-budget-gda.h"
+#include "gnc-slots-gda.h"
+#include "gnc-recurrence-gda.h"
+
+#include "gnc-budget.h"
+
+#define BUDGET_TABLE "budgets"
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define BUDGET_MAX_NAME_LEN 50
+#define BUDGET_MAX_DESCRIPTION_LEN 500
+
+static col_cvt_t col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "name", CT_STRING, BUDGET_MAX_NAME_LEN, COL_NNUL, NULL, "name" },
+ { "description", CT_STRING, BUDGET_MAX_DESCRIPTION_LEN, 0, NULL, "description" },
+ { "num_periods", CT_INT, 0, COL_NNUL, NULL, "num_periods" },
+ { NULL }
+};
+
+/* ================================================================= */
+static GncBudget*
+load_single_budget( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ const GUID* guid;
+ GUID budget_guid;
+ GncBudget* pBudget;
+ Recurrence* r;
+
+ guid = gnc_gda_load_guid( be, pModel, row );
+ budget_guid = *guid;
+
+ pBudget = gnc_budget_lookup( &budget_guid, be->primary_book );
+ if( pBudget == NULL ) {
+ pBudget = gnc_budget_new( be->primary_book );
+ }
+
+ gnc_gda_load_object( be, pModel, row, GNC_ID_BUDGET, pBudget, col_table );
+ r = g_new0( Recurrence, 1 );
+ gnc_gda_recurrence_load( be, gnc_budget_get_guid( pBudget ), r );
+ gnc_gda_slots_load( be, gnc_budget_get_guid( pBudget ),
+ qof_instance_get_slots( QOF_INSTANCE(pBudget) ) );
+
+ qof_instance_mark_clean( QOF_INSTANCE(pBudget) );
+
+ return pBudget;
+}
+
+static void
+load_all_budgets( GncGdaBackend* be )
+{
+ static GdaQuery* query;
+ GdaObject* ret;
+ QofBook* pBook = be->primary_book;
+
+ if( query == NULL ) {
+ query = gnc_gda_create_select_query( be, BUDGET_TABLE );
+ }
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+
+ for( r = 0; r < numRows; r++ ) {
+ (void)load_single_budget( be, pModel, r );
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_budget_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, BUDGET_TABLE, col_table );
+}
+
+/* ================================================================= */
+void
+gnc_gda_save_budget( GncGdaBackend* be, QofInstance* inst )
+{
+ GncBudget* pBudget = GNC_BUDGET(inst);
+ const GUID* guid;
+
+ (void)gnc_gda_do_db_operation( be,
+ qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE,
+ BUDGET_TABLE,
+ GNC_ID_BUDGET, pBudget,
+ col_table );
+
+ // Now, commit any slots and recurrence
+ guid = qof_instance_get_guid( inst );
+ if( !qof_instance_get_destroying(inst) ) {
+ gnc_gda_recurrence_save( be, guid, gnc_budget_get_recurrence( pBudget ) );
+ gnc_gda_slots_save( be, guid, qof_instance_get_slots( inst ) );
+ } else {
+ gnc_gda_recurrence_delete( be, guid );
+ gnc_gda_slots_delete( be, guid );
+ }
+}
+
+/* ================================================================= */
+void
+gnc_gda_init_budget_handler( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_BUDGET,
+ gnc_gda_save_budget, /* commit */
+ load_all_budgets, /* initial_load */
+ create_budget_tables /* create_tables */
+ };
+
+ qof_object_register_backend( GNC_ID_BUDGET, GNC_GDA_BACKEND, &be_data );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-budget-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-budget-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-budget-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,38 @@
+/********************************************************************
+ * gnc-budget-gda.h: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-budget-gda.h
+ * @brief load and save data to SQL via libgda
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_BUDGET_GDA_H_
+#define GNC_BUDGET_GDA_H_
+
+#include "qof.h"
+#include <gmodule.h>
+
+void gnc_gda_init_budget_handler( void );
+void gnc_gda_save_budget( GncGdaBackend* be, QofInstance* inst );
+
+#endif /* GNC_BUDGET_GDA_H_ */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-commodity-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-commodity-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-commodity-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,220 @@
+/********************************************************************
+ * gnc-commodity-gda.c: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-commodity-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/
+ * restoring data to/from an SQL db using libgda
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <libgda/libgda.h>
+
+#include "qof.h"
+
+#include "gnc-backend-util-gda.h"
+#include "gnc-commodity.h"
+
+#include "gnc-commodity-gda.h"
+#include "gnc-slots-gda.h"
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+static gpointer get_quote_source_name( gpointer pObject, const QofParam* );
+static void set_quote_source_name( gpointer pObject, gpointer pValue );
+
+#define COMMODITIES_TABLE "commodities"
+
+#define COMMODITY_MAX_NAMESPACE_LEN 40
+#define COMMODITY_MAX_MNEMONIC_LEN 40
+#define COMMODITY_MAX_FULLNAME_LEN 100
+#define COMMODITY_MAX_CUSIP_LEN 50
+#define COMMODITY_MAX_QUOTESOURCE_LEN 50
+#define COMMODITY_MAX_QUOTE_TZ_LEN 50
+
+static col_cvt_t col_table[] = {
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "namespace", CT_STRING, COMMODITY_MAX_NAMESPACE_LEN, COL_NNUL, NULL, NULL,
+ (QofAccessFunc)gnc_commodity_get_namespace,
+ (QofSetterFunc)gnc_commodity_set_namespace },
+ { "mnemonic", CT_STRING, COMMODITY_MAX_MNEMONIC_LEN, COL_NNUL, NULL, NULL,
+ (QofAccessFunc)gnc_commodity_get_mnemonic,
+ (QofSetterFunc)gnc_commodity_set_mnemonic },
+ { "fullname", CT_STRING, COMMODITY_MAX_FULLNAME_LEN, COL_NNUL, NULL, NULL,
+ (QofAccessFunc)gnc_commodity_get_fullname,
+ (QofSetterFunc)gnc_commodity_set_fullname },
+ { "cusip", CT_STRING, COMMODITY_MAX_CUSIP_LEN, 0, NULL, NULL,
+ (QofAccessFunc)gnc_commodity_get_cusip,
+ (QofSetterFunc)gnc_commodity_set_cusip },
+ { "fraction", CT_INT, 0, COL_NNUL, NULL, NULL,
+ (QofAccessFunc)gnc_commodity_get_fraction,
+ (QofSetterFunc)gnc_commodity_set_fraction },
+ { "quote_flag", CT_INT, 0, COL_NNUL, NULL, NULL,
+ (QofAccessFunc)gnc_commodity_get_quote_flag,
+ (QofSetterFunc)gnc_commodity_set_quote_flag },
+ { "quote_source", CT_STRING, COMMODITY_MAX_QUOTESOURCE_LEN, 0, NULL, NULL,
+ get_quote_source_name, set_quote_source_name },
+ { "quote_tz", CT_STRING, COMMODITY_MAX_QUOTE_TZ_LEN, 0, NULL, NULL,
+ (QofAccessFunc)gnc_commodity_get_quote_tz,
+ (QofSetterFunc)gnc_commodity_set_quote_tz },
+ { NULL }
+};
+
+/* ================================================================= */
+
+static gpointer
+get_quote_source_name( gpointer pObject, const QofParam* param )
+{
+ const 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, 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_single_commodity( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ QofBook* pBook = be->primary_book;
+ int col;
+ const GValue* val;
+ gnc_commodity* pCommodity;
+
+ pCommodity = gnc_commodity_new( pBook, NULL, NULL, NULL, NULL, 100 );
+
+ gnc_gda_load_object( be, pModel, row, GNC_ID_COMMODITY, pCommodity, col_table );
+ gnc_gda_slots_load( be, qof_instance_get_guid( QOF_INSTANCE(pCommodity) ),
+ qof_instance_get_slots( QOF_INSTANCE(pCommodity) ) );
+
+ qof_instance_mark_clean( QOF_INSTANCE(pCommodity) );
+
+ return pCommodity;
+}
+
+static void
+load_all_commodities( GncGdaBackend* be )
+{
+ static GdaQuery* query;
+ GdaObject* ret;
+ gnc_commodity_table* pTable = gnc_commodity_table_get_table( be->primary_book );
+
+ if( query == NULL ) {
+ query = gnc_gda_create_select_query( be, COMMODITIES_TABLE );
+ }
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+ gnc_commodity* pCommodity;
+
+ for( r = 0; r < numRows; r++ ) {
+ gnc_commodity* c;
+
+ pCommodity = load_single_commodity( be, pModel, r );
+
+ if( pCommodity != NULL ) {
+ GUID guid;
+
+ guid = *qof_instance_get_guid( QOF_INSTANCE(pCommodity) );
+ pCommodity = gnc_commodity_table_insert( pTable, pCommodity );
+ qof_instance_set_guid( QOF_INSTANCE(pCommodity), &guid );
+ }
+ }
+ }
+}
+/* ================================================================= */
+static void
+create_commodities_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, COMMODITIES_TABLE, col_table );
+}
+
+/* ================================================================= */
+static void
+commit_commodity( GncGdaBackend* be, QofInstance* inst )
+{
+ const GUID* guid;
+
+ (void)gnc_gda_do_db_operation( be,
+ (qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+ COMMODITIES_TABLE,
+ GNC_ID_COMMODITY, (gnc_commodity*)inst,
+ col_table );
+
+ // Delete old slot info
+ guid = qof_instance_get_guid( inst );
+
+ // Now, commit or delete any slots
+ if( !qof_instance_get_destroying(inst) ) {
+ gnc_gda_slots_save( be, guid, qof_instance_get_slots( inst ) );
+ } else {
+ gnc_gda_slots_delete( be, guid );
+ }
+}
+
+static gboolean
+is_commodity_in_db( GncGdaBackend* be, gnc_commodity* pCommodity )
+{
+ return gnc_gda_object_is_it_in_db( be, COMMODITIES_TABLE, GNC_ID_COMMODITY,
+ pCommodity, col_table );
+}
+
+void
+gnc_gda_save_commodity( GncGdaBackend* be, gnc_commodity* pCommodity )
+{
+ if( !is_commodity_in_db( be, pCommodity ) ) {
+ commit_commodity( be, QOF_INSTANCE(pCommodity) );
+ }
+}
+
+/* ================================================================= */
+void
+gnc_gda_init_commodity_handler( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_COMMODITY,
+ commit_commodity, /* commit */
+ load_all_commodities, /* initial_load */
+ create_commodities_tables /* create_tables */
+ };
+
+ qof_object_register_backend( GNC_ID_COMMODITY, GNC_GDA_BACKEND, &be_data );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-commodity-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-commodity-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-commodity-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,38 @@
+/********************************************************************
+ * gnc-commodity-gda.h: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-commodity-gda.h
+ * @brief load and save data to SQL via libgda
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_COMMODITY_GDA_H_
+#define GNC_COMMODITY_GDA_H_
+
+#include "qof.h"
+#include <gmodule.h>
+
+void gnc_gda_init_commodity_handler( void );
+void gnc_gda_save_commodity( GncGdaBackend* be, gnc_commodity* pCommodity );
+
+#endif /* GNC_COMMODITY_GDA_H_ */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-lots-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-lots-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-lots-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,178 @@
+/********************************************************************
+ * gnc-lots-gda.c: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-lots-gda.c
+ * @brief load and save data to SQL
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL db using libgda
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <libgda/libgda.h>
+
+#include "qof.h"
+#include "gnc-lot.h"
+
+#include "gnc-backend-util-gda.h"
+#include "gnc-slots-gda.h"
+
+#include "gnc-lots-gda.h"
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define TABLE_NAME "lots"
+
+static gpointer get_lot_account( gpointer pObject, const QofParam* param );
+static void set_lot_account( gpointer pObject, gpointer pValue );
+static gpointer get_lot_is_closed( gpointer pObject, const QofParam* param );
+static void set_lot_is_closed( gpointer pObject, gpointer pValue );
+
+static col_cvt_t col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "account_guid", CT_GUID, 0, COL_NNUL, NULL, NULL, get_lot_account, set_lot_account },
+ { "is_closed", CT_STRING, 1, COL_NNUL, NULL, NULL, get_lot_is_closed, set_lot_is_closed },
+ { NULL }
+};
+
+/* ================================================================= */
+static gpointer
+get_lot_account( gpointer pObject, const QofParam* param )
+{
+ const GNCLot* lot = GNC_LOT(pObject);
+ const Account* pAccount = gnc_lot_get_account( lot );
+
+ return (gpointer)qof_instance_get_guid( QOF_INSTANCE(pAccount) );
+}
+
+static void
+set_lot_account( gpointer pObject, gpointer pValue )
+{
+ GNCLot* lot = GNC_LOT(pObject);
+ QofBook* pBook = qof_instance_get_book( QOF_INSTANCE(lot) );
+ GUID* guid = (GUID*)pValue;
+ Account* pAccount = xaccAccountLookup( guid, pBook );
+
+ xaccAccountInsertLot( pAccount, lot );
+}
+
+static gpointer
+get_lot_is_closed( gpointer pObject, const QofParam* param )
+{
+ GNCLot* lot = GNC_LOT(pObject);
+ static gboolean is_closed;
+
+ is_closed = gnc_lot_is_closed( lot );
+ return &is_closed;
+}
+
+static void
+set_lot_is_closed( gpointer pObject, gpointer pValue )
+{
+ GNCLot* lot = GNC_LOT(pObject);
+ const gboolean* pBoolean = (const gboolean*)pValue;
+
+ lot->is_closed = *pBoolean;
+}
+
+static GNCLot*
+load_single_lot( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ GNCLot* lot;
+
+ lot = gnc_lot_new( be->primary_book );
+
+ gnc_gda_load_object( be, pModel, row, GNC_ID_LOT, lot, col_table );
+ gnc_gda_slots_load( be, qof_instance_get_guid( QOF_INSTANCE(lot) ),
+ qof_instance_get_slots( QOF_INSTANCE(lot) ) );
+
+ qof_instance_mark_clean( QOF_INSTANCE(lot) );
+
+ return lot;
+}
+
+static void
+load_all_lots( GncGdaBackend* be )
+{
+ static GdaQuery* query;
+ GdaObject* ret;
+
+ if( query == NULL ) {
+ query = gnc_gda_create_select_query( be, TABLE_NAME );
+ }
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+ GNCLot* lot;
+
+ for( r = 0; r < numRows; r++ ) {
+ lot = load_single_lot( be, pModel, r );
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_lots_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, TABLE_NAME, col_table );
+}
+
+/* ================================================================= */
+
+static void
+commit_lot( GncGdaBackend* be, QofInstance* inst )
+{
+ GNCLot* lot = GNC_LOT(inst);
+
+ (void)gnc_gda_do_db_operation( be,
+ (qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+ TABLE_NAME,
+ GNC_ID_LOT, lot,
+ col_table );
+
+ // Now, commit any slots
+ gnc_gda_slots_save( be, qof_instance_get_guid( inst ),
+ qof_instance_get_slots( inst ) );
+}
+
+/* ================================================================= */
+void
+gnc_gda_init_lot_handler( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_LOT,
+ commit_lot, /* commit */
+ load_all_lots, /* initial_load */
+ create_lots_tables /* create tables */
+ };
+
+ qof_object_register_backend( GNC_ID_LOT, GNC_GDA_BACKEND, &be_data );
+}
+
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-lots-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-lots-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-lots-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,37 @@
+/********************************************************************
+ * gnc-lots-gda.h: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-lots-gda.h
+ * @brief load and save data to SQL via libgda
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_LOT_GDA_H_
+#define GNC_LOT_GDA_H_
+
+#include "qof.h"
+#include <gmodule.h>
+
+void gnc_gda_init_lot_handler( void );
+
+#endif /* GNC_LOT_GDA_H_ */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-price-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-price-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-price-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,168 @@
+/********************************************************************
+ * gnc-price-gda.c: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-price-gda.c
+ * @brief load and save data to SQL
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL db using libgda
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <libgda/libgda.h>
+
+#include "qof.h"
+#include "gnc-pricedb.h"
+
+#include "gnc-backend-util-gda.h"
+
+#include "gnc-commodity-gda.h"
+#include "gnc-price-gda.h"
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define TABLE_NAME "prices"
+
+static gpointer get_date( gpointer pObject, const QofParam* param );
+static void set_date( gpointer pObject, gpointer pValue );
+
+#define PRICE_MAX_SOURCE_LEN 50
+#define PRICE_MAX_TYPE_LEN 50
+
+static col_cvt_t col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "commodity_guid", CT_COMMODITYREF, 0, COL_NNUL, NULL, PRICE_COMMODITY },
+ { "currency_guid", CT_COMMODITYREF, 0, COL_NNUL, NULL, PRICE_CURRENCY },
+ { "date", CT_TIMESPEC, 0, COL_NNUL, NULL, NULL, get_date, set_date },
+ { "source", CT_STRING, PRICE_MAX_SOURCE_LEN, 0, NULL, PRICE_SOURCE },
+ { "type", CT_STRING, PRICE_MAX_TYPE_LEN, 0, NULL, PRICE_TYPE },
+ { "value", CT_NUMERIC, 0, COL_NNUL, NULL, PRICE_VALUE },
+ { NULL }
+};
+
+/* ================================================================= */
+
+static gpointer
+get_date( gpointer pObject, const QofParam* param )
+{
+ const GNCPrice* pPrice = GNC_PRICE(pObject);
+ static Timespec t;
+
+ t = gnc_price_get_time( pPrice );
+ return &t;
+}
+
+static void
+set_date( gpointer pObject, gpointer pValue )
+{
+ GNCPrice* pPrice = GNC_PRICE(pObject);
+ const Timespec* pTimespec = (const Timespec*)pValue;
+
+ gnc_price_set_time( pPrice, *pTimespec );
+}
+
+static GNCPrice*
+load_single_price( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ GNCPrice* pPrice;
+
+ pPrice = gnc_price_create( be->primary_book );
+
+ gnc_gda_load_object( be, pModel, row, GNC_ID_PRICE, pPrice, col_table );
+
+ qof_instance_mark_clean( QOF_INSTANCE(pPrice) );
+
+ return pPrice;
+}
+
+static void
+load_all_prices( GncGdaBackend* be )
+{
+ static GdaQuery* query;
+ GdaObject* ret;
+ QofBook* pBook = be->primary_book;
+ GNCPriceDB* pPriceDB = gnc_book_get_pricedb( pBook );
+
+ if( query == NULL ) {
+ query = gnc_gda_create_select_query( be, TABLE_NAME );
+ }
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+ GNCPrice* pPrice;
+
+ for( r = 0; r < numRows; r++ ) {
+ pPrice = load_single_price( be, pModel, r );
+
+ if( pPrice != NULL ) {
+ gnc_pricedb_add_price( pPriceDB, pPrice );
+ }
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_prices_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, TABLE_NAME, col_table );
+}
+
+/* ================================================================= */
+
+void
+gnc_gda_save_price( GncGdaBackend* be, QofInstance* inst )
+{
+ GNCPrice* pPrice = GNC_PRICE(inst);
+
+ /* Ensure commodity and currency are in the db */
+ gnc_gda_save_commodity( be, gnc_price_get_commodity( pPrice ) );
+ gnc_gda_save_commodity( be, gnc_price_get_currency( pPrice ) );
+
+ (void)gnc_gda_do_db_operation( be,
+ (qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+ TABLE_NAME,
+ GNC_ID_PRICE, pPrice,
+ col_table );
+}
+
+/* ================================================================= */
+void
+gnc_gda_init_price_handler( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_PRICE,
+ gnc_gda_save_price, /* commit */
+ load_all_prices, /* initial_load */
+ create_prices_tables /* create tables */
+ };
+
+ qof_object_register_backend( GNC_ID_PRICE, GNC_GDA_BACKEND, &be_data );
+}
+
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-price-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-price-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-price-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,38 @@
+/********************************************************************
+ * gnc-price-gda.h: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-price-gda.h
+ * @brief load and save data to SQL via libgda
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_PRICE_GDA_H_
+#define GNC_PRICE_GDA_H_
+
+#include "qof.h"
+#include <gmodule.h>
+
+void gnc_gda_init_price_handler( void );
+void gnc_gda_save_price( GncGdaBackend* be, QofInstance* inst );
+
+#endif /* GNC_PRICE_GDA_H_ */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-recurrence-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-recurrence-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-recurrence-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,349 @@
+/********************************************************************
+ * gnc-recurrence-gda.c: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-recurrence-gda.c
+ * @brief load and save data to SQL
+ * @author Copyright (c) 2006, 2007 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL db using libgda
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <libgda/libgda.h>
+
+#include "qof.h"
+#include "gnc-engine.h"
+#include "Recurrence.h"
+
+#include "gnc-backend-util-gda.h"
+
+#include "gnc-recurrence-gda.h"
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define TABLE_NAME "recurrences"
+
+#define BUDGET_MAX_RECURRENCE_PERIOD_TYPE_LEN 50
+
+typedef struct {
+ GncGdaBackend* be;
+ const GUID* guid;
+ Recurrence* pRecurrence;
+} recurrence_info_t;
+
+static gpointer get_recurrence_id( gpointer pObject, const QofParam* param );
+static void set_recurrence_id( gpointer pObject, gpointer pValue );
+static gpointer get_obj_guid( gpointer pObject, const QofParam* param );
+static void set_obj_guid( gpointer pObject, gpointer pValue );
+static gpointer get_recurrence_mult( gpointer pObject, const QofParam* );
+static void set_recurrence_mult( gpointer pObject, gpointer pValue );
+static gpointer get_recurrence_period_type( gpointer pObject, const QofParam* );
+static void set_recurrence_period_type( gpointer pObject, gpointer pValue );
+static gpointer get_recurrence_period_start( gpointer pObject, const QofParam* );
+static void set_recurrence_period_start( gpointer pObject, gpointer pValue );
+
+static col_cvt_t col_table[] =
+{
+ { "recurrence_id", CT_INT, 0, COL_NNUL|COL_AUTOINC, NULL, NULL,
+ get_recurrence_id, set_recurrence_id },
+ { "obj_guid", CT_GUID, 0, COL_NNUL, NULL, NULL,
+ get_obj_guid, set_obj_guid },
+ { "recurrence_mult", CT_INT, 0, COL_NNUL, NULL, NULL,
+ get_recurrence_mult, set_recurrence_mult },
+ { "recurrence_period_type", CT_STRING, BUDGET_MAX_RECURRENCE_PERIOD_TYPE_LEN, COL_NNUL, NULL, NULL,
+ get_recurrence_period_type, set_recurrence_period_type },
+ { "recurrence_period_start", CT_GDATE, 0, COL_NNUL, NULL, NULL,
+ get_recurrence_period_start, set_recurrence_period_start },
+ { NULL }
+};
+
+/* Special column table because we need to be able to access the table by
+a column other than the primary key */
+static col_cvt_t guid_col_table[] =
+{
+ { "obj_guid", CT_GUID, 0, 0, NULL, NULL, get_obj_guid, set_obj_guid },
+ { NULL }
+};
+
+/* ================================================================= */
+
+static gpointer
+get_recurrence_id( gpointer pObject, const QofParam* param )
+{
+ // Just need a 0 to force a new recurrence id
+ return (gpointer)0;
+}
+
+static void
+set_recurrence_id( gpointer pObject, gpointer pValue )
+{
+ // Nowhere to put the ID
+}
+
+static gpointer
+get_obj_guid( gpointer pObject, const QofParam* param )
+{
+ recurrence_info_t* pInfo = (recurrence_info_t*)pObject;
+
+ return (gpointer)pInfo->guid;
+}
+
+static void
+set_obj_guid( gpointer pObject, gpointer pValue )
+{
+ // Nowhere to put the GUID
+}
+
+static gpointer
+get_recurrence_mult( gpointer pObject, const QofParam* param )
+{
+ recurrence_info_t* pInfo = (recurrence_info_t*)pObject;
+ static guint m;
+
+ m = pInfo->pRecurrence->mult;
+
+ return GUINT_TO_POINTER(m);
+}
+
+static void
+set_recurrence_mult( gpointer pObject, gpointer pValue )
+{
+ recurrence_info_t* pInfo = (recurrence_info_t*)pObject;
+ guint m = GPOINTER_TO_UINT(pValue);
+
+ pInfo->pRecurrence->mult = m;
+}
+
+static gpointer
+get_recurrence_period_type( gpointer pObject, const QofParam* param )
+{
+ recurrence_info_t* pInfo = (recurrence_info_t*)pObject;
+
+ return (gpointer)recurrencePeriodTypeToString(
+ recurrenceGetPeriodType( pInfo->pRecurrence ) );
+}
+
+static void
+set_recurrence_period_type( gpointer pObject, gpointer pValue )
+{
+ recurrence_info_t* pInfo = (recurrence_info_t*)pObject;
+
+ pInfo->pRecurrence->ptype = recurrencePeriodTypeFromString( (gchar*)pValue );
+}
+
+static gpointer
+get_recurrence_period_start( gpointer pObject, const QofParam* param )
+{
+ recurrence_info_t* pInfo = (recurrence_info_t*)pObject;
+ static GDate date;
+
+ date = recurrenceGetDate( pInfo->pRecurrence );
+ return (gpointer)&date;
+}
+
+static void
+set_recurrence_period_start( gpointer pObject, gpointer pValue )
+{
+ recurrence_info_t* pInfo = (recurrence_info_t*)pObject;
+ GDate* date = (GDate*)pValue;
+
+ pInfo->pRecurrence->start = *date;
+}
+
+/* ================================================================= */
+
+void
+gnc_gda_recurrence_save( GncGdaBackend* be, const GUID* guid, const Recurrence* r )
+{
+ recurrence_info_t recurrence_info;
+
+ gnc_gda_recurrence_delete( be, guid );
+
+ recurrence_info.be = be;
+ recurrence_info.guid = guid;
+ recurrence_info.pRecurrence = (Recurrence*)r;
+ (void)gnc_gda_do_db_operation( be, OP_DB_ADD, TABLE_NAME,
+ TABLE_NAME, &recurrence_info, col_table );
+}
+
+void
+gnc_gda_recurrence_save_list( GncGdaBackend* be, const GUID* guid, GList* schedule )
+{
+ recurrence_info_t recurrence_info;
+ GList* l;
+
+ gnc_gda_recurrence_delete( be, guid );
+
+ recurrence_info.be = be;
+ recurrence_info.guid = guid;
+ for( l = schedule; l != NULL; l = g_list_next( l ) ) {
+ recurrence_info.pRecurrence = (Recurrence*)l->data;
+ (void)gnc_gda_do_db_operation( be, OP_DB_ADD, TABLE_NAME,
+ TABLE_NAME, &recurrence_info, col_table );
+ }
+}
+
+void
+gnc_gda_recurrence_delete( GncGdaBackend* be, const GUID* guid )
+{
+ recurrence_info_t recurrence_info;
+
+ recurrence_info.be = be;
+ recurrence_info.guid = guid;
+ (void)gnc_gda_do_db_operation( be, OP_DB_DELETE, TABLE_NAME,
+ TABLE_NAME, &recurrence_info, guid_col_table );
+}
+
+static void
+load_recurrence( GncGdaBackend* be, GdaDataModel* pModel, gint row, Recurrence* r )
+{
+ recurrence_info_t recurrence_info;
+
+ recurrence_info.be = be;
+ recurrence_info.pRecurrence = r;
+
+ gnc_gda_load_object( be, pModel, row, TABLE_NAME, &recurrence_info, col_table );
+}
+
+static GdaObject*
+gnc_gda_set_recurrences_from_db( GncGdaBackend* be, const GUID* guid )
+{
+ gchar* buf;
+ GdaObject* ret;
+ gchar guid_buf[GUID_ENCODING_LENGTH+1];
+ gchar* field_name;
+
+ static GdaQuery* query = NULL;
+ GdaQueryCondition* cond;
+ GdaQueryField* key_value;
+ GValue value;
+
+ guid_to_string_buff( guid, guid_buf );
+
+ /* First time, create the query */
+ if( query == NULL ) {
+ GdaQueryTarget* target;
+ GdaQueryField* key;
+
+ /* SELECT */
+ query = gnc_gda_create_select_query( be, TABLE_NAME );
+ target = gda_query_get_target_by_alias( query, TABLE_NAME );
+
+ /* WHERE */
+ cond = gda_query_condition_new( query, GDA_QUERY_CONDITION_LEAF_EQUAL );
+ gda_query_set_condition( query, cond );
+
+ field_name = g_strdup_printf( "%s.%s",
+ gda_query_target_get_alias( target ), "obj_guid" );
+ key = gda_query_field_field_new( query, field_name );
+ g_free( field_name );
+ gda_query_field_set_visible( key, TRUE );
+ gda_query_condition_leaf_set_operator( cond,
+ GDA_QUERY_CONDITION_OP_LEFT,
+ GDA_QUERY_FIELD(key) );
+ g_object_unref( G_OBJECT(key) );
+
+ key_value = gda_query_field_value_new( query, G_TYPE_STRING );
+ gda_query_field_set_visible( key_value, TRUE );
+ gda_query_condition_leaf_set_operator( cond, GDA_QUERY_CONDITION_OP_RIGHT,
+ GDA_QUERY_FIELD(key_value) );
+ g_object_unref( G_OBJECT(key_value) );
+ }
+
+ /* Fill in the guid value */
+ cond = gda_query_get_condition( query );
+ key_value = gda_query_condition_leaf_get_operator( cond,
+ GDA_QUERY_CONDITION_OP_RIGHT );
+ memset( &value, 0, sizeof( value ) );
+ g_value_init( &value, G_TYPE_STRING );
+ g_value_set_string( &value, guid_buf );
+ gda_query_field_value_set_value( GDA_QUERY_FIELD_VALUE(key_value), &value );
+
+ ret = gnc_gda_execute_query( be, query );
+
+ return ret;
+}
+
+void
+gnc_gda_recurrence_load( GncGdaBackend* be, const GUID* guid, Recurrence* pRecurrence )
+{
+ GdaObject* ret;
+
+ ret = gnc_gda_set_recurrences_from_db( be, guid );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+
+ if( numRows > 0 ) {
+ if( numRows > 1 ) {
+ g_warning( "More than 1 recurrence found: first one used" );
+ }
+ load_recurrence( be, pModel, 0, pRecurrence );
+ } else {
+ g_warning( "No recurrences found" );
+ }
+ }
+}
+
+void
+gnc_gda_recurrence_load_list( GncGdaBackend* be, const GUID* guid, GList** pSchedule )
+{
+ GdaObject* ret;
+
+ ret = gnc_gda_set_recurrences_from_db( be, guid );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+
+ for( r = 0; r < numRows; r++ ) {
+ Recurrence* pRecurrence = g_new0( Recurrence, 1 );
+ load_recurrence( be, pModel, 0, pRecurrence );
+ *pSchedule = g_list_append( *pSchedule, pRecurrence );
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_recurrence_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, TABLE_NAME, col_table );
+}
+
+/* ================================================================= */
+void
+gnc_gda_init_recurrence_handler( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_ACCOUNT,
+ NULL, /* commit - cannot occur */
+ NULL, /* initial_load - cannot occur */
+ create_recurrence_tables /* create_tables */
+ };
+
+ qof_object_register_backend( TABLE_NAME, GNC_GDA_BACKEND, &be_data );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-recurrence-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-recurrence-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-recurrence-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,43 @@
+/********************************************************************
+ * gnc-recurrence-gda.h: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-recurrence-gda.h
+ * @brief load and save accounts data to SQL via libgda
+ * @author Copyright (c) 2006-2007 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_RECURRENCE_GDA_H_
+#define GNC_RECURRENCE_GDA_H_
+
+#include "qof.h"
+#include <gmodule.h>
+
+void gnc_gda_recurrence_save( GncGdaBackend* be, const GUID* guid, const Recurrence* pRecurrence );
+void gnc_gda_recurrence_save_list( GncGdaBackend* be, const GUID* guid, GList* schedule );
+void gnc_gda_recurrence_delete( GncGdaBackend* be, const GUID* guid );
+void gnc_gda_recurrence_load( GncGdaBackend* be, const GUID* guid, Recurrence* pRecurrence );
+void gnc_gda_recurrence_load_list( GncGdaBackend* be, const GUID* guid, GList** pSchedule );
+
+void gnc_gda_init_recurrence_handler( void );
+
+#endif /* GNC_RECURRENCE_GDA_H_ */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-schedxaction-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-schedxaction-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-schedxaction-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,245 @@
+/********************************************************************
+ * gnc-schedxaction-gda.c: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-schedxaction-gda.c
+ * @brief load and save data to SQL
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL db using libgda
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <libgda/libgda.h>
+
+#include "qof.h"
+
+#include "gnc-backend-util-gda.h"
+
+#include "gnc-schedxaction-gda.h"
+#include "gnc-slots-gda.h"
+
+#include "SchedXaction.h"
+#include "SX-book.h"
+#include "Recurrence.h"
+
+#include "gnc-recurrence-gda.h"
+
+#define SCHEDXACTION_TABLE "schedxactions"
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define SX_MAX_NAME_LEN 50
+
+static gpointer get_autocreate( gpointer pObject, const QofParam* param );
+static void set_autocreate( gpointer pObject, gpointer pValue );
+static gpointer get_autonotify( gpointer pObject, const QofParam* param );
+static void set_autonotify( gpointer pObject, gpointer pValue );
+static gpointer get_template_act_guid( gpointer pObject, const QofParam* param );
+static void set_template_act_guid( gpointer pObject, gpointer pValue );
+
+static col_cvt_t col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "name", CT_STRING, SX_MAX_NAME_LEN, 0, NULL, GNC_SX_NAME },
+ { "start_date", CT_GDATE, 0, COL_NNUL, NULL, GNC_SX_START_DATE },
+ { "last_occur", CT_GDATE, 0, 0, NULL, GNC_SX_LAST_DATE },
+ { "num_occur", CT_INT, 0, COL_NNUL, NULL, GNC_SX_NUM_OCCUR },
+ { "rem_occur", CT_INT, 0, COL_NNUL, NULL, GNC_SX_REM_OCCUR },
+ { "auto_create", CT_BOOLEAN, 0, COL_NNUL, NULL, NULL, get_autocreate, set_autocreate },
+ { "auto_notify", CT_BOOLEAN, 0, COL_NNUL, NULL, NULL, get_autonotify, set_autonotify },
+ { "adv_creation", CT_INT, 0, COL_NNUL, NULL, NULL,
+ (QofAccessFunc)xaccSchedXactionGetAdvanceCreation,
+ (QofSetterFunc)xaccSchedXactionSetAdvanceCreation },
+ { "adv_notify", CT_INT, 0, COL_NNUL, NULL, NULL,
+ (QofAccessFunc)xaccSchedXactionGetAdvanceReminder,
+ (QofSetterFunc)xaccSchedXactionSetAdvanceReminder },
+ { "template_act_guid", CT_GUID, 0, COL_NNUL, NULL, NULL, get_template_act_guid, set_template_act_guid },
+ { NULL }
+};
+
+/* ================================================================= */
+
+static gpointer
+get_autocreate( gpointer pObject, const QofParam* param )
+{
+ const SchedXaction* pSx = GNC_SX(pObject);
+ gboolean autoCreate;
+ gboolean autoNotify;
+
+ xaccSchedXactionGetAutoCreate( pSx, &autoCreate, &autoNotify );
+ return GINT_TO_POINTER(autoCreate);
+}
+
+static void
+set_autocreate( gpointer pObject, gpointer pValue )
+{
+ SchedXaction* pSx = GNC_SX(pObject);
+ gboolean autoCreate;
+ gboolean autoNotify;
+
+ xaccSchedXactionGetAutoCreate( pSx, &autoCreate, &autoNotify );
+ autoCreate = GPOINTER_TO_INT(pValue);
+ xaccSchedXactionSetAutoCreate( pSx, autoCreate, autoNotify );
+}
+
+static gpointer
+get_autonotify( gpointer pObject, const QofParam* param )
+{
+ const SchedXaction* pSx = GNC_SX(pObject);
+ gboolean autoCreate;
+ gboolean autoNotify;
+
+ xaccSchedXactionGetAutoCreate( pSx, &autoCreate, &autoNotify );
+ return GINT_TO_POINTER(autoNotify);
+}
+
+static void
+set_autonotify( gpointer pObject, gpointer pValue )
+{
+ SchedXaction* pSx = GNC_SX(pObject);
+ gboolean autoCreate;
+ gboolean autoNotify;
+
+ xaccSchedXactionGetAutoCreate( pSx, &autoCreate, &autoNotify );
+ autoNotify = GPOINTER_TO_INT(pValue);
+ xaccSchedXactionSetAutoCreate( pSx, autoCreate, autoNotify );
+}
+
+static gpointer
+get_template_act_guid( gpointer pObject, const QofParam* param )
+{
+ const SchedXaction* pSx = GNC_SX(pObject);
+
+ return (gpointer)xaccAccountGetGUID( pSx->template_acct );
+}
+
+static void
+set_template_act_guid( gpointer pObject, gpointer pValue )
+{
+ SchedXaction* pSx = GNC_SX(pObject);
+ QofBook* pBook = qof_instance_get_book( QOF_INSTANCE(pSx) );
+ GUID* guid = (GUID*)pValue;
+ Account* pAcct;
+
+ pAcct = xaccAccountLookup( guid, pBook );
+ sx_set_template_account( pSx, pAcct );
+}
+
+/* ================================================================= */
+static SchedXaction*
+load_single_sx( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ const GUID* guid;
+ GUID sx_guid;
+ SchedXaction* pSx;
+ GList* schedule = NULL;
+
+ guid = gnc_gda_load_guid( be, pModel, row );
+ sx_guid = *guid;
+
+ pSx = xaccSchedXactionMalloc( be->primary_book );
+
+ gnc_gda_load_object( be, pModel, row, /*GNC_ID_SCHEDXACTION*/GNC_SX_ID, pSx, col_table );
+ gnc_gda_recurrence_load_list( be, guid, &schedule );
+ gnc_sx_set_schedule( pSx, schedule );
+ gnc_gda_slots_load( be, qof_instance_get_guid( QOF_INSTANCE(pSx) ),
+ qof_instance_get_slots( QOF_INSTANCE(pSx) ) );
+
+ qof_instance_mark_clean( QOF_INSTANCE(pSx) );
+
+ return pSx;
+}
+
+static void
+load_all_sxes( GncGdaBackend* be )
+{
+ static GdaQuery* query;
+ GdaObject* ret;
+ QofBook* pBook = be->primary_book;
+
+ if( query == NULL ) {
+ query = gnc_gda_create_select_query( be, SCHEDXACTION_TABLE );
+ }
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+ SchedXactions *sxes;
+ sxes = gnc_book_get_schedxactions( be->primary_book );
+
+ for( r = 0; r < numRows; r++ ) {
+ SchedXaction* sx;
+
+ sx = load_single_sx( be, pModel, r );
+ gnc_sxes_add_sx(sxes, sx);
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_sx_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, SCHEDXACTION_TABLE, col_table );
+}
+
+/* ================================================================= */
+void
+gnc_gda_save_schedxaction( GncGdaBackend* be, QofInstance* inst )
+{
+ SchedXaction* pSx = GNC_SX(inst);
+ const GUID* guid;
+
+ (void)gnc_gda_do_db_operation( be,
+ (qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+ SCHEDXACTION_TABLE,
+ /*GNC_ID_SCHEDXACTION*/GNC_SX_ID, pSx,
+ col_table );
+ gnc_gda_recurrence_save_list( be, guid, gnc_sx_get_schedule( pSx ) );
+
+ // Now, commit any slots
+ guid = qof_instance_get_guid( inst );
+ if( !qof_instance_get_destroying(inst) ) {
+ gnc_gda_slots_save( be, guid, qof_instance_get_slots( inst ) );
+ } else {
+ gnc_gda_slots_delete( be, guid );
+ }
+}
+
+/* ================================================================= */
+void
+gnc_gda_init_schedxaction_handler( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_SCHEDXACTION,
+ gnc_gda_save_schedxaction, /* commit */
+ load_all_sxes, /* initial_load */
+ create_sx_tables /* create_tables */
+ };
+
+ qof_object_register_backend( GNC_ID_SCHEDXACTION, GNC_GDA_BACKEND, &be_data );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-schedxaction-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-schedxaction-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-schedxaction-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,38 @@
+/********************************************************************
+ * gnc-schedxaction-gda.h: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-backend-gda.h
+ * @brief load and save data to SQL via libgda
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_SCHEDXACTION_GDA_H_
+#define GNC_SCHEDXACTION_GDA_H_
+
+#include "qof.h"
+#include <gmodule.h>
+
+void gnc_gda_init_schedxaction_handler( void );
+void gnc_gda_save_schedxaction( GncGdaBackend* be, QofInstance* inst );
+
+#endif /* GNC_SCHEDXACTION_GDA_H_ */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-slots-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-slots-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-slots-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,455 @@
+/********************************************************************
+ * gnc-slots-gda.c: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-slots-gda.c
+ * @brief load and save data to SQL
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL db using libgda
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <libgda/libgda.h>
+
+#include "qof.h"
+#include "gnc-engine.h"
+
+#include "gnc-backend-util-gda.h"
+
+#include "gnc-slots-gda.h"
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define TABLE_NAME "slots"
+
+typedef struct {
+ GncGdaBackend* be;
+ const GUID* guid;
+ KvpFrame* pKvpFrame;
+ KvpValueType value_type;
+ KvpValue* pKvpValue;
+ GString* path;
+} slot_info_t;
+
+static gpointer get_slot_id( gpointer pObject, const QofParam* param );
+static void set_slot_id( gpointer pObject, gpointer pValue );
+static gpointer get_obj_guid( gpointer pObject, const QofParam* param );
+static void set_obj_guid( gpointer pObject, gpointer pValue );
+static gpointer get_path( gpointer pObject, const QofParam* param );
+static void set_path( gpointer pObject, gpointer pValue );
+static gpointer get_slot_type( gpointer pObject, const QofParam* param );
+static void set_slot_type( gpointer pObject, gpointer pValue );
+static gpointer get_int64_val( gpointer pObject, const QofParam* param );
+static void set_int64_val( gpointer pObject, gpointer pValue );
+static gpointer get_string_val( gpointer pObject, const QofParam* param );
+static void set_string_val( gpointer pObject, gpointer pValue );
+static gpointer get_double_val( gpointer pObject, const QofParam* param );
+static void set_double_val( gpointer pObject, gpointer pValue );
+static gpointer get_timespec_val( gpointer pObject, const QofParam* param );
+static void set_timespec_val( gpointer pObject, gpointer pValue );
+static gpointer get_guid_val( gpointer pObject, const QofParam* param );
+static void set_guid_val( gpointer pObject, gpointer pValue );
+static gnc_numeric get_numeric_val( gpointer pObject, const QofParam* param );
+static void set_numeric_val( gpointer pObject, gnc_numeric value );
+
+#define SLOT_MAX_PATHNAME_LEN 500
+#define SLOT_MAX_STRINGVAL_LEN 1000
+
+static col_cvt_t col_table[] =
+{
+ { "slot_id", CT_INT, 0, COL_NNUL|COL_AUTOINC, NULL, NULL, get_slot_id, set_slot_id },
+ { "obj_guid", CT_GUID, 0, COL_NNUL, NULL, NULL, get_obj_guid, set_obj_guid },
+ { "name", CT_STRING, SLOT_MAX_PATHNAME_LEN, COL_NNUL, NULL, NULL, get_path, set_path },
+ { "slot_type", CT_INT, 0, COL_NNUL, NULL, NULL, get_slot_type, set_slot_type, },
+ { "int64_val", CT_INT64, 0, 0, NULL, NULL, get_int64_val, set_int64_val },
+ { "string_val", CT_STRING, SLOT_MAX_PATHNAME_LEN, 0, NULL, NULL, get_string_val, set_string_val },
+ { "double_val", CT_DOUBLE, 0, 0, NULL, NULL, get_double_val, set_double_val },
+ { "timespec_val", CT_TIMESPEC, 0, 0, NULL, NULL, get_timespec_val, set_timespec_val },
+ { "guid_val", CT_GUID, 0, 0, NULL, NULL, get_guid_val, set_guid_val },
+ { "numeric_val", CT_NUMERIC, 0, 0, NULL, NULL,
+ (QofAccessFunc)get_numeric_val, (QofSetterFunc)set_numeric_val },
+ { NULL }
+};
+
+/* Special column table because we need to be able to access the table by
+a column other than the primary key */
+static col_cvt_t guid_col_table[] =
+{
+ { "obj_guid", CT_GUID, 0, 0, NULL, NULL, get_obj_guid, set_obj_guid },
+ { NULL }
+};
+
+/* ================================================================= */
+
+static gpointer
+get_slot_id( gpointer pObject, const QofParam* param )
+{
+ // Just need a 0 to force a new slot id
+ return (gpointer)0;
+}
+
+static void
+set_slot_id( gpointer pObject, gpointer pValue )
+{
+ // Nowhere to put the ID
+}
+
+static gpointer
+get_obj_guid( gpointer pObject, const QofParam* param )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+
+ return (gpointer)pInfo->guid;
+}
+
+static void
+set_obj_guid( gpointer pObject, gpointer pValue )
+{
+ // Nowhere to put the GUID
+}
+
+static gpointer
+get_path( gpointer pObject, const QofParam* param )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+
+ return (gpointer)pInfo->path->str;
+}
+
+static void
+set_path( gpointer pObject, gpointer pValue )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+
+ pInfo->path = g_string_new( (gchar*)pValue );
+}
+
+static gpointer
+get_slot_type( gpointer pObject, const QofParam* param )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+
+ return (gpointer)kvp_value_get_type( pInfo->pKvpValue );
+}
+
+static void
+set_slot_type( gpointer pObject, gpointer pValue )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+
+ pInfo->value_type = (KvpValueType)pValue;
+}
+
+static gpointer
+get_int64_val( gpointer pObject, const QofParam* param )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+ static gint64 i64_val;
+
+ if( kvp_value_get_type( pInfo->pKvpValue ) == KVP_TYPE_GINT64 ) {
+ i64_val = kvp_value_get_gint64( pInfo->pKvpValue );
+ return &i64_val;
+ } else {
+ return NULL;
+ }
+}
+
+static void
+set_int64_val( gpointer pObject, gpointer pValue )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+
+ if( pInfo->value_type == KVP_TYPE_GINT64 ) {
+ kvp_frame_set_gint64( pInfo->pKvpFrame, pInfo->path->str, *(gint64*)pValue );
+ }
+}
+
+static gpointer
+get_string_val( gpointer pObject, const QofParam* param )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+
+ if( kvp_value_get_type( pInfo->pKvpValue ) == KVP_TYPE_STRING ) {
+ return (gpointer)kvp_value_get_string( pInfo->pKvpValue );
+ } else {
+ return NULL;
+ }
+}
+
+static void
+set_string_val( gpointer pObject, gpointer pValue )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+
+ if( pInfo->value_type == KVP_TYPE_STRING ) {
+ kvp_frame_set_string( pInfo->pKvpFrame, pInfo->path->str, (const gchar*)pValue );
+ }
+}
+
+static gpointer
+get_double_val( gpointer pObject, const QofParam* param )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+ static double d_val;
+
+ if( kvp_value_get_type( pInfo->pKvpValue ) == KVP_TYPE_DOUBLE ) {
+ d_val = kvp_value_get_double( pInfo->pKvpValue );
+ return (gpointer)&d_val;
+ } else {
+ return NULL;
+ }
+}
+
+static void
+set_double_val( gpointer pObject, gpointer pValue )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+
+ if( pInfo->value_type == KVP_TYPE_DOUBLE ) {
+ kvp_frame_set_double( pInfo->pKvpFrame, pInfo->path->str, *(double*)pValue );
+ }
+}
+
+static gpointer
+get_timespec_val( gpointer pObject, const QofParam* param )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+ static Timespec ts;
+
+ if( kvp_value_get_type( pInfo->pKvpValue ) == KVP_TYPE_TIMESPEC ) {
+ ts = kvp_value_get_timespec( pInfo->pKvpValue );
+ return (gpointer)&ts;
+ } else {
+ return NULL;
+ }
+}
+
+static void
+set_timespec_val( gpointer pObject, gpointer pValue )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+
+ if( pInfo->value_type == KVP_TYPE_TIMESPEC ) {
+ kvp_frame_set_timespec( pInfo->pKvpFrame, pInfo->path->str, *(Timespec*)pValue );
+ }
+}
+
+static gpointer
+get_guid_val( gpointer pObject, const QofParam* param )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+
+ if( kvp_value_get_type( pInfo->pKvpValue ) == KVP_TYPE_GUID ) {
+ return (gpointer)kvp_value_get_guid( pInfo->pKvpValue );
+ } else {
+ return NULL;
+ }
+}
+
+static void
+set_guid_val( gpointer pObject, gpointer pValue )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+
+ if( pInfo->value_type == KVP_TYPE_GUID ) {
+ kvp_frame_set_guid( pInfo->pKvpFrame, pInfo->path->str, (GUID*)pValue );
+ }
+}
+
+static gnc_numeric
+get_numeric_val( gpointer pObject, const QofParam* param )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+
+ if( kvp_value_get_type( pInfo->pKvpValue ) == KVP_TYPE_NUMERIC ) {
+ return kvp_value_get_numeric( pInfo->pKvpValue );
+ } else {
+ return gnc_numeric_zero();
+ }
+}
+
+static void
+set_numeric_val( gpointer pObject, gnc_numeric value )
+{
+ slot_info_t* pInfo = (slot_info_t*)pObject;
+
+ if( pInfo->value_type == KVP_TYPE_NUMERIC ) {
+ kvp_frame_set_numeric( pInfo->pKvpFrame, pInfo->path->str, value );
+ }
+}
+
+static void
+save_slot( const gchar* key, KvpValue* value, gpointer data )
+{
+ slot_info_t* pSlot_info = (slot_info_t*)data;
+ gint curlen = pSlot_info->path->len;
+
+ pSlot_info->pKvpValue = value;
+ if( curlen != 0 ) {
+ g_string_append( pSlot_info->path, "/" );
+ }
+ g_string_append( pSlot_info->path, key );
+
+ if( kvp_value_get_type( value ) == KVP_TYPE_FRAME ) {
+ KvpFrame* pKvpFrame = kvp_value_get_frame( value );
+ kvp_frame_for_each_slot( pKvpFrame, save_slot, pSlot_info );
+ } else {
+ (void)gnc_gda_do_db_operation( pSlot_info->be, OP_DB_ADD, TABLE_NAME,
+ TABLE_NAME, pSlot_info, col_table );
+ }
+
+ g_string_truncate( pSlot_info->path, curlen );
+}
+
+void
+gnc_gda_slots_save( GncGdaBackend* be, const GUID* guid, KvpFrame* pFrame )
+{
+ slot_info_t slot_info;
+
+ /* First, delete the old slots for this object */
+ gnc_gda_slots_delete( be, guid );
+
+ slot_info.be = be;
+ slot_info.guid = guid;
+ slot_info.path = g_string_new( "" );
+ kvp_frame_for_each_slot( pFrame, save_slot, &slot_info );
+ g_string_free( slot_info.path, FALSE );
+}
+
+void
+gnc_gda_slots_delete( GncGdaBackend* be, const GUID* guid )
+{
+ slot_info_t slot_info;
+
+ slot_info.be = be;
+ slot_info.guid = guid;
+ (void)gnc_gda_do_db_operation( be, OP_DB_DELETE, TABLE_NAME,
+ TABLE_NAME, &slot_info, guid_col_table );
+}
+
+static void
+load_slot( GncGdaBackend* be, GdaDataModel* pModel, gint row, KvpFrame* pFrame )
+{
+ slot_info_t slot_info;
+
+ slot_info.be = be;
+ slot_info.pKvpFrame = pFrame;
+ slot_info.path = NULL;
+
+ gnc_gda_load_object( be, pModel, row, TABLE_NAME, &slot_info, col_table );
+
+ if( slot_info.path != NULL ) {
+ g_string_free( slot_info.path, TRUE );
+ }
+}
+
+void
+gnc_gda_slots_load( GncGdaBackend* be, const GUID* guid, KvpFrame* pFrame )
+{
+ gchar* buf;
+ GdaObject* ret;
+ gchar guid_buf[GUID_ENCODING_LENGTH+1];
+ gchar* field_name;
+
+ static GdaQuery* query = NULL;
+ GdaQueryCondition* cond;
+ GdaQueryField* key_value;
+ GValue value;
+
+ guid_to_string_buff( guid, guid_buf );
+
+ /* First time, create the query */
+ if( query == NULL ) {
+ GdaQueryTarget* target;
+ GdaQueryField* key;
+
+ /* SELECT */
+ query = gnc_gda_create_select_query( be, TABLE_NAME );
+ target = gda_query_get_target_by_alias( query, TABLE_NAME );
+
+ /* WHERE */
+ cond = gda_query_condition_new( query, GDA_QUERY_CONDITION_LEAF_EQUAL );
+ gda_query_set_condition( query, cond );
+
+ field_name = g_strdup_printf( "%s.%s",
+ gda_query_target_get_alias( target ), "obj_guid" );
+ key = gda_query_field_field_new( query, field_name );
+ g_free( field_name );
+ gda_query_field_set_visible( key, TRUE );
+ gda_query_condition_leaf_set_operator( cond,
+ GDA_QUERY_CONDITION_OP_LEFT,
+ GDA_QUERY_FIELD(key) );
+ g_object_unref( G_OBJECT(key) );
+
+ key_value = gda_query_field_value_new( query, G_TYPE_STRING );
+ gda_query_field_set_visible( key_value, TRUE );
+ gda_query_condition_leaf_set_operator( cond, GDA_QUERY_CONDITION_OP_RIGHT,
+ GDA_QUERY_FIELD(key_value) );
+ g_object_unref( G_OBJECT(key_value) );
+ }
+
+ /* Fill in the guid value */
+ cond = gda_query_get_condition( query );
+ key_value = gda_query_condition_leaf_get_operator( cond,
+ GDA_QUERY_CONDITION_OP_RIGHT );
+ memset( &value, 0, sizeof( value ) );
+ g_value_init( &value, G_TYPE_STRING );
+ g_value_set_string( &value, guid_buf );
+ gda_query_field_value_set_value( GDA_QUERY_FIELD_VALUE(key_value), &value );
+
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+ KvpValue* pValue;
+
+ for( r = 0; r < numRows; r++ ) {
+ load_slot( be, pModel, r, pFrame );
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_slots_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, TABLE_NAME, col_table );
+}
+
+/* ================================================================= */
+void
+gnc_gda_init_slots_handler( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_ACCOUNT,
+ NULL, /* commit - cannot occur */
+ NULL, /* initial_load - cannot occur */
+ create_slots_tables /* create_tables */
+ };
+
+ qof_object_register_backend( TABLE_NAME, GNC_GDA_BACKEND, &be_data );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-slots-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-slots-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-slots-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,41 @@
+/********************************************************************
+ * gnc-slots-gda.h: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-slots-gda.h
+ * @brief load and save accounts data to SQL via libgda
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_SLOTS_GDA_H_
+#define GNC_SLOTS_GDA_H_
+
+#include "qof.h"
+#include <gmodule.h>
+
+void gnc_gda_slots_save( GncGdaBackend* be, const GUID* guid, KvpFrame* pFrame );
+void gnc_gda_slots_delete( GncGdaBackend* be, const GUID* guid );
+void gnc_gda_slots_load( GncGdaBackend* be, const GUID* guid, KvpFrame* pFrame );
+
+void gnc_gda_init_slots_handler( void );
+
+#endif /* GNC_SLOTS_GDA_H_ */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-transaction-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-transaction-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-transaction-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,741 @@
+/********************************************************************
+ * gnc-transaction-gda.c: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-transaction-gda.c
+ * @brief load and save data to SQL
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL db using libgda
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <libgda/libgda.h>
+
+#include "qof.h"
+#include "qofquery-p.h"
+#include "qofquerycore-p.h"
+
+#include "Account.h"
+#include "Transaction.h"
+
+#include "gnc-backend-util-gda.h"
+#include "gnc-transaction-gda.h"
+#include "gnc-commodity.h"
+#include "gnc-commodity-gda.h"
+#include "gnc-slots-gda.h"
+
+#include "gnc-engine.h"
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define TRANSACTION_TABLE "transactions"
+#define SPLIT_TABLE "splits"
+
+typedef struct {
+ GncGdaBackend* be;
+ const GUID* guid;
+} split_info_t;
+
+static gpointer get_tx_post_date( gpointer pObject, const QofParam* param );
+static void set_tx_post_date( gpointer pObject, gpointer pValue );
+static gpointer get_tx_enter_date( gpointer pObject, const QofParam* param );
+static void set_tx_enter_date( gpointer pObject, gpointer pValue );
+
+#define TX_MAX_NUM_LEN 50
+#define TX_MAX_DESCRIPTION_LEN 500
+
+static col_cvt_t tx_col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "currency_guid", CT_COMMODITYREF, 0, COL_NNUL, NULL, NULL,
+ (QofAccessFunc)xaccTransGetCurrency, (QofSetterFunc)xaccTransSetCurrency },
+ { "num", CT_STRING, TX_MAX_NUM_LEN, COL_NNUL, NULL, TRANS_NUM },
+ { "post_date", CT_TIMESPEC, 0, COL_NNUL, NULL, NULL, get_tx_post_date, set_tx_post_date },
+ { "enter_date", CT_TIMESPEC, 0, COL_NNUL, NULL, NULL, get_tx_enter_date, set_tx_enter_date },
+ { "description", CT_STRING, TX_MAX_DESCRIPTION_LEN, 0, NULL, NULL,
+ (QofAccessFunc)xaccTransGetDescription, (QofSetterFunc)xaccTransSetDescription },
+ { NULL }
+};
+
+static gpointer get_split_reconcile_state( gpointer pObject, const QofParam* param );
+static void set_split_reconcile_state( gpointer pObject, gpointer pValue );
+static gpointer get_split_reconcile_date( gpointer pObject, const QofParam* param );
+static void set_split_reconcile_date( gpointer pObject, gpointer pValue );
+
+#define SPLIT_MAX_MEMO_LEN 50
+#define SPLIT_MAX_ACTION_LEN 50
+
+static col_cvt_t split_col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "tx_guid", CT_TXREF, 0, COL_NNUL, NULL, SPLIT_TRANS },
+ { "account_guid", CT_ACCOUNTREF, 0, COL_NNUL, NULL, SPLIT_ACCOUNT },
+ { "memo", CT_STRING, SPLIT_MAX_MEMO_LEN, COL_NNUL, NULL, SPLIT_MEMO },
+ { "action", CT_STRING, SPLIT_MAX_ACTION_LEN, COL_NNUL, NULL, SPLIT_ACTION },
+ { "reconcile_state", CT_STRING, 1, COL_NNUL, NULL, NULL, get_split_reconcile_state, set_split_reconcile_state },
+ { "reconcile_date", CT_TIMESPEC, 0, COL_NNUL, NULL, NULL, get_split_reconcile_date, set_split_reconcile_date },
+ { "value", CT_NUMERIC, 0, COL_NNUL, NULL, SPLIT_VALUE },
+ { "quantity", CT_NUMERIC, 0, COL_NNUL, NULL, SPLIT_AMOUNT },
+ { NULL }
+};
+
+static col_cvt_t guid_col_table[] =
+{
+ { "tx_guid", CT_GUID, 0, 0, "guid" },
+ { NULL }
+};
+
+static void retrieve_numeric_value( gpointer pObject, gnc_numeric value );
+
+/* ================================================================= */
+
+static gpointer
+get_tx_post_date( gpointer pObject, const QofParam* param )
+{
+ const Transaction* pTx = GNC_TRANS(pObject);
+ static Timespec ts;
+
+ ts = xaccTransRetDatePostedTS( pTx );
+ return (gpointer)&ts;
+}
+
+static void
+set_tx_post_date( gpointer pObject, gpointer pValue )
+{
+ Transaction* pTx = GNC_TRANS(pObject);
+ Timespec* pTS = (Timespec*)pValue;
+
+ xaccTransSetDatePostedTS( pTx, pTS );
+}
+
+static gpointer
+get_tx_enter_date( gpointer pObject, const QofParam* param )
+{
+ const Transaction* pTx = GNC_TRANS(pObject);
+ static Timespec ts;
+
+ ts = xaccTransRetDateEnteredTS( pTx );
+ return (gpointer)&ts;
+}
+
+static void
+set_tx_enter_date( gpointer pObject, gpointer pValue )
+{
+ Transaction* pTx = GNC_TRANS(pObject);
+ Timespec* pTS = (Timespec*)pValue;
+
+ xaccTransSetDateEnteredTS( pTx, pTS );
+}
+
+static gpointer
+get_split_reconcile_state( gpointer pObject, const QofParam* param )
+{
+ const Split* pSplit = GNC_SPLIT(pObject);
+ static gchar c[2];
+
+ c[0] = xaccSplitGetReconcile( pSplit );
+ c[1] = '\0';
+ return (gpointer)c;
+}
+
+static void
+set_split_reconcile_state( gpointer pObject, gpointer pValue )
+{
+ Split* pSplit = GNC_SPLIT(pObject);
+ const gchar* s = (const gchar*)pValue;
+
+ xaccSplitSetReconcile( pSplit, s[0] );
+}
+
+static gpointer
+get_split_reconcile_date( gpointer pObject, const QofParam* param )
+{
+ const Split* pSplit = GNC_SPLIT(pObject);
+ static Timespec ts;
+
+ ts = xaccSplitRetDateReconciledTS( pSplit );
+ return (gpointer)&ts;
+}
+
+static void
+set_split_reconcile_date( gpointer pObject, gpointer pValue )
+{
+ Split* pSplit = GNC_SPLIT(pObject);
+ Timespec* pTS = (Timespec*)pValue;
+
+ xaccSplitSetDateReconciledTS( pSplit, pTS );
+}
+
+static void
+retrieve_numeric_value( gpointer pObject, gnc_numeric value )
+{
+ gnc_numeric* pResult = (gnc_numeric*)pObject;
+ *pResult = value;
+}
+
+
+// Table to retrieve just the quantity
+static col_cvt_t quantity_table[] =
+{
+ { "quantity", CT_NUMERIC, 0, COL_NNUL, NULL, NULL, NULL, (QofSetterFunc)retrieve_numeric_value },
+ { NULL }
+};
+
+static gnc_numeric
+get_gnc_numeric_from_row( GncGdaBackend* be, GdaDataModel* model, int row )
+{
+ gnc_numeric val;
+
+ gnc_gda_load_object( be, model, row, NULL, &val, quantity_table );
+
+ return val;
+}
+
+/*
+ * get_account_balance_from_query
+ *
+ * Given a GDA query which should return a number of rows of gnc_numeric num/denom pairs,
+ * return the sum.
+ */
+static gnc_numeric
+get_account_balance_from_query( GncGdaBackend* be, GdaQuery* query )
+{
+ gnc_numeric bal = gnc_numeric_zero();
+ GdaObject* ret;
+
+ /* Execute the query */
+ ret = gnc_gda_execute_query( be, query );
+
+ /* Loop for all rows, convert each to a gnc_numeric and sum them */
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+
+ for( r = 0; r < numRows; r++ ) {
+ gnc_numeric val = get_gnc_numeric_from_row( be, pModel, r );
+ bal = gnc_numeric_add( bal, val, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
+ }
+ }
+
+ return bal;
+}
+
+void
+gnc_gda_get_account_balances( GncGdaBackend* be, Account* pAccount,
+ gnc_numeric* start_balance,
+ gnc_numeric* cleared_balance,
+ gnc_numeric* reconciled_balance )
+{
+ GdaQuery* query;
+ gchar guid_buf[GUID_ENCODING_LENGTH+1];
+ gchar* sql;
+
+ guid_to_string_buff( qof_instance_get_guid( pAccount ), guid_buf );
+
+ /*
+ * For start balance,
+ * SELECT SUM(QUANTITY_NUM),QUANTITY_DENOM FROM SPLITS
+ * WHERE ACCOUNT_GUID=<guid> GROUP BY QUANTITY_DENOM
+ *
+ * This will return one entry per denom. These can then be made into
+ * gnc_numerics and then added. With luck, there will only be one entry.
+ */
+
+ //sql = g_strdup_printf( "SELECT SUM(QUANTITY_NUM),QUANTITY_DENOM FROM %s WHERE ACCOUNT_GUID='%s' GROUP BY QUANTITY_DENOM", SPLIT_TABLE, guid_buf );
+ sql = g_strdup_printf( "SELECT QUANTITY_NUM,QUANTITY_DENOM FROM %s WHERE ACCOUNT_GUID='%s' GROUP BY QUANTITY_DENOM", SPLIT_TABLE, guid_buf );
+
+ /* Create the query */
+ query = gnc_gda_create_query_from_sql( be, sql );
+ *start_balance = get_account_balance_from_query( be, query );
+
+ g_free( sql );
+
+ /*
+ * For cleared balance,
+ * SELECT SUM(QUANTITY_NUM),QUANTITY_DENOM FROM SPLITS
+ * WHERE ACCOUNT_GUID=<guid> AND RECONCILE_STATE='c'
+ * GROUP BY QUANTITY_DENOM
+ *
+ * This just requires a modification to the query
+ */
+
+ //sql = g_strdup_printf( "SELECT SUM(QUANTITY_NUM),QUANTITY_DENOM FROM %s WHERE ACCOUNT_GUID='%s' AND RECONCILE_STATE='%c' GROUP BY QUANTITY_DENOM", SPLIT_TABLE, guid_buf, CREC );
+ sql = g_strdup_printf( "SELECT QUANTITY_NUM,QUANTITY_DENOM FROM %s WHERE ACCOUNT_GUID='%s' AND RECONCILE_STATE='%c' GROUP BY QUANTITY_DENOM", SPLIT_TABLE, guid_buf, CREC );
+
+ query = gnc_gda_create_query_from_sql( be, sql );
+ *cleared_balance = get_account_balance_from_query( be, query );
+
+ g_free( sql );
+
+ /*
+ * For reconciled balance,
+ * SELECT SUM(QUANTITY_NUM),QUANTITY_DENOM FROM SPLITS
+ * WHERE ACCOUNT_GUID=<guid> AND RECONCILE_STATE='c'
+ * GROUP BY QUANTITY_DENOM
+ *
+ * This just requires a small modification to the cleared balance query
+ */
+
+ //sql = g_strdup_printf( "SELECT SUM(QUANTITY_NUM),QUANTITY_DENOM FROM %s WHERE ACCOUNT_GUID='%s' AND RECONCILE_STATE='%c' GROUP BY QUANTITY_DENOM", SPLIT_TABLE, guid_buf, YREC );
+ sql = g_strdup_printf( "SELECT QUANTITY_NUM,QUANTITY_DENOM FROM %s WHERE ACCOUNT_GUID='%s' AND RECONCILE_STATE='%c' GROUP BY QUANTITY_DENOM", SPLIT_TABLE, guid_buf, YREC );
+
+ query = gnc_gda_create_query_from_sql( be, sql );
+ *reconciled_balance = get_account_balance_from_query( be, query );
+
+ g_free( sql );
+}
+
+static Split*
+load_single_split( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ const GUID* guid;
+ GUID split_guid;
+ Split* pSplit;
+
+ guid = gnc_gda_load_guid( be, pModel, row );
+ split_guid = *guid;
+
+ pSplit = xaccSplitLookup( &split_guid, be->primary_book );
+ if( pSplit == NULL ) {
+ pSplit = xaccMallocSplit( be->primary_book );
+ }
+
+ /* If the split is dirty, don't overwrite it */
+ if( qof_instance_is_dirty( QOF_INSTANCE(pSplit) ) ) {
+ return pSplit;
+ }
+
+ gnc_gda_load_object( be, pModel, row, GNC_ID_SPLIT, pSplit, split_col_table );
+
+ gnc_gda_slots_load( be, qof_instance_get_guid( QOF_INSTANCE(pSplit) ),
+ qof_instance_get_slots( QOF_INSTANCE(pSplit) ) );
+
+ g_assert( pSplit == xaccSplitLookup( &split_guid, be->primary_book ) );
+
+ //qof_instance_mark_clean( QOF_INSTANCE(pSplit) );
+
+ return pSplit;
+}
+
+static void
+load_all_splits( GncGdaBackend* be, const GUID* tx_guid )
+{
+ GdaObject* ret;
+ gchar guid_buf[GUID_ENCODING_LENGTH+1];
+ GdaQuery* query;
+ GdaQueryCondition* cond;
+ GValue value;
+
+ guid_to_string_buff( tx_guid, guid_buf );
+ memset( &value, 0, sizeof( GValue ) );
+ g_value_init( &value, G_TYPE_STRING );
+ g_value_set_string( &value, guid_buf );
+ query = gnc_gda_create_select_query( be, SPLIT_TABLE );
+ cond = gnc_gda_create_condition_from_field( query, "tx_guid", &value );
+ gda_query_set_condition( query, cond );
+ g_object_unref( G_OBJECT(cond) );
+
+ ret = gnc_gda_execute_query( be, query );
+ g_object_unref( G_OBJECT(query) );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+
+ for( r = 0; r < numRows; r++ ) {
+ load_single_split( be, pModel, r );
+ }
+ }
+}
+
+static Transaction*
+load_single_tx( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ const GUID* guid;
+ GUID tx_guid;
+ Transaction* pTx;
+
+ guid = gnc_gda_load_guid( be, pModel, row );
+ tx_guid = *guid;
+
+ pTx = xaccTransLookup( &tx_guid, be->primary_book );
+ if( pTx == NULL ) {
+ pTx = xaccMallocTransaction( be->primary_book );
+ }
+ xaccTransBeginEdit( pTx );
+ gnc_gda_load_object( be, pModel, row, GNC_ID_TRANS, pTx, tx_col_table );
+ gnc_gda_slots_load( be, qof_instance_get_guid( QOF_INSTANCE(pTx) ),
+ qof_instance_get_slots( QOF_INSTANCE(pTx) ) );
+ load_all_splits( be, qof_instance_get_guid( QOF_INSTANCE(pTx) ) );
+
+ qof_instance_mark_clean( QOF_INSTANCE(pTx) );
+ xaccTransCommitEdit( pTx );
+
+ g_assert( pTx == xaccTransLookup( &tx_guid, be->primary_book ) );
+
+ return pTx;
+}
+
+static void
+query_transactions( GncGdaBackend* be, GdaQuery* query )
+{
+ GdaObject* ret;
+
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+
+ for( r = 0; r < numRows; r++ ) {
+ load_single_tx( be, pModel, r );
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_transaction_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, TRANSACTION_TABLE, tx_col_table );
+ gnc_gda_create_table_if_needed( be, SPLIT_TABLE, split_col_table );
+}
+/* ================================================================= */
+static void
+delete_split_slots_cb( gpointer data, gpointer user_data )
+{
+ split_info_t* split_info = (split_info_t*)user_data;
+ Split* pSplit = GNC_SPLIT(data);
+
+ gnc_gda_slots_delete( split_info->be,
+ qof_instance_get_guid( QOF_INSTANCE(pSplit) ) );
+}
+
+static void
+delete_splits( GncGdaBackend* be, Transaction* pTx )
+{
+ split_info_t split_info;
+
+ (void)gnc_gda_do_db_operation( be, OP_DB_DELETE, SPLIT_TABLE,
+ SPLIT_TABLE, pTx, guid_col_table );
+ split_info.be = be;
+
+ g_list_foreach( xaccTransGetSplitList( pTx ), delete_split_slots_cb, &split_info );
+}
+
+static void
+commit_split( GncGdaBackend* be, QofInstance* inst )
+{
+ Split* pSplit = GNC_SPLIT(inst);
+
+ (void)gnc_gda_do_db_operation( be,
+ (qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+ SPLIT_TABLE,
+ GNC_ID_SPLIT, pSplit,
+ split_col_table );
+ gnc_gda_slots_save( be,
+ qof_instance_get_guid( QOF_INSTANCE(pSplit) ),
+ qof_instance_get_slots( QOF_INSTANCE(pSplit) ) );
+}
+
+static void
+save_split_cb( gpointer data, gpointer user_data )
+{
+ split_info_t* split_info = (split_info_t*)user_data;
+ Split* pSplit = GNC_SPLIT(data);
+
+ commit_split( split_info->be, QOF_INSTANCE(pSplit) );
+}
+
+static void
+save_splits( GncGdaBackend* be, const GUID* tx_guid, SplitList* pSplitList )
+{
+ split_info_t split_info;
+
+ split_info.be = be;
+ split_info.guid = tx_guid;
+ g_list_foreach( pSplitList, save_split_cb, &split_info );
+}
+
+void
+gnc_gda_save_transaction( GncGdaBackend* be, QofInstance* inst )
+{
+ Transaction* pTx = GNC_TRANS(inst);
+ const GUID* guid;
+
+ // Ensure the commodity is in the db
+ gnc_gda_save_commodity( be, xaccTransGetCurrency( pTx ) );
+
+ (void)gnc_gda_do_db_operation( be,
+ (qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+ TRANSACTION_TABLE,
+ GNC_ID_TRANS, pTx,
+ tx_col_table );
+
+ guid = qof_instance_get_guid( inst );
+
+ // Delete any old slots and splits for this transaction
+ delete_splits( be, pTx );
+
+ if( !qof_instance_get_destroying(inst) ) {
+ SplitList* splits;
+
+ // Now, commit any slots and splits
+ gnc_gda_slots_save( be, guid, qof_instance_get_slots( inst ) );
+ splits = xaccTransGetSplitList( pTx );
+ save_splits( be, guid, splits );
+
+ /* Mark the splits as clean */
+ splits = xaccTransGetSplitList( pTx );
+ for( ; splits != NULL; splits = splits->next ) {
+ QofInstance* inst = QOF_INSTANCE(splits->data);
+
+ qof_instance_mark_clean(inst);
+ }
+ } else {
+ gnc_gda_slots_delete( be, guid );
+ }
+}
+
+void gnc_gda_transaction_commit_splits( GncGdaBackend* be, Transaction* pTx )
+{
+ SplitList* splits;
+ Split* s;
+ QofBackend* qbe = (QofBackend*)be;
+
+ splits = xaccTransGetSplitList( pTx );
+ for( ; splits != NULL; splits = splits->next ) {
+ s = GNC_SPLIT(splits->data);
+
+ qbe->commit( qbe, QOF_INSTANCE(s) );
+ }
+}
+
+/* ================================================================= */
+static const GUID*
+get_guid_from_query( QofQuery* pQuery )
+{
+ GList* pOrTerms = qof_query_get_terms( pQuery );
+ GList* pAndTerms;
+ GList* andTerm;
+ QofQueryTerm* pTerm;
+ QofQueryPredData* pPredData;
+ GSList* pParamPath;
+
+ pAndTerms = (GList*)pOrTerms->data;
+ andTerm = pAndTerms->next;
+ pTerm = (QofQueryTerm*)andTerm->data;
+
+ pPredData = qof_query_term_get_pred_data( pTerm );
+ pParamPath = qof_query_term_get_param_path( pTerm );
+
+ if( strcmp( pPredData->type_name, "guid" ) == 0 ) {
+ query_guid_t pData = (query_guid_t)pPredData;
+ return pData->guids->data;
+ } else {
+ return NULL;
+ }
+}
+
+static gpointer
+compile_split_query( GncGdaBackend* be, QofQuery* pQuery )
+{
+ gchar* buf;
+ const GUID* acct_guid;
+ gchar guid_buf[GUID_ENCODING_LENGTH+1];
+ gchar* s;
+
+#if 1
+ GdaQuery* query;
+ GdaObject* results;
+
+ acct_guid = get_guid_from_query( pQuery );
+ guid_to_string_buff( acct_guid, guid_buf );
+ buf = g_strdup_printf( "SELECT DISTINCT tx_guid FROM %s WHERE account_guid='%s'", SPLIT_TABLE, guid_buf );
+ results = gnc_gda_execute_sql( be, buf );
+ g_free( buf );
+ if( GDA_IS_DATA_MODEL( results ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(results);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+
+ if( numRows != 1 ) {
+ buf = g_strdup_printf( "SELECT * FROM %s WHERE guid IN (", TRANSACTION_TABLE );
+ } else {
+ buf = g_strdup_printf( "SELECT * FROM %s WHERE guid =", TRANSACTION_TABLE );
+ }
+
+ for( r = 0; r < numRows; r++ ) {
+ const GUID* guid;
+
+ guid = gnc_gda_load_tx_guid( be, pModel, r );
+ guid_to_string_buff( guid, guid_buf );
+ if( r == 0 ) {
+ s = g_strconcat( buf, "'", guid_buf, "'", NULL );
+ } else {
+ s = g_strconcat( buf, ",'", guid_buf, "'", NULL );
+ }
+ g_free( buf );
+ buf = s;
+ }
+
+ if( numRows != 1 ) {
+ s = g_strconcat( buf, ")", NULL );
+ g_free( buf );
+ buf = s;
+ }
+ }
+
+ return buf;
+#else
+#if 1
+ acct_guid = get_guid_from_query( pQuery );
+ guid_to_string_buff( acct_guid, guid_buf );
+ buf = g_strdup_printf( "SELECT * FROM %s WHERE guid IN (SELECT DISTINCT tx_guid FROM %s WHERE account_guid = '%s')",
+ TRANSACTION_TABLE, SPLIT_TABLE, guid_buf );
+ return buf;
+#else
+ GdaQuery* query;
+ GdaQuery* subQuery;
+ GdaQueryTarget* target;
+ GdaQueryField* allFields;
+ GdaQueryField* field;
+ GValue value;
+ GdaQueryCondition* cond;
+ GdaQueryField* key;
+ GdaQueryField* key_value;
+
+ acct_guid = get_guid_from_query( pQuery );
+ guid_to_string_buff( acct_guid, guid_buf );
+
+ /* Subquery */
+
+ /* SELECT */
+ subQuery = gda_query_new( be->pDict );
+ gda_query_set_query_type( subQuery, GDA_QUERY_TYPE_SELECT );
+
+ /* FROM splits */
+ target = gda_query_target_new( subQuery, SPLIT_TABLE );
+ gda_query_add_target( subQuery, target, NULL );
+ g_object_unref( G_OBJECT(target) );
+
+ /* tx_guid */
+ field = gda_query_field_field_new( subQuery, "tx_guid" );
+ gda_query_field_set_visible( field, TRUE );
+ gda_entity_add_field( GDA_ENTITY(subQuery), GDA_ENTITY_FIELD(field) );
+ g_object_unref( G_OBJECT(field) );
+
+ /* WHERE */
+ memset( &value, 0, sizeof( GValue ) );
+ g_value_init( &value, G_TYPE_STRING );
+ g_value_set_string( &value, guid_buf );
+ cond = gnc_gda_create_condition_from_field( subQuery, "account_guid", &value );
+ gda_query_set_condition( subQuery, cond );
+ g_object_unref( G_OBJECT(cond) );
+
+ /* Main query */
+
+ /* SELECT * FROM transactions */
+ query = gnc_gda_create_select_query( be, TRANSACTION_TABLE );
+ gda_query_add_sub_query( query, subQuery );
+ g_object_unref( G_OBJECT(subQuery) );
+
+ /* WHERE */
+ cond = gda_query_condition_new( query, GDA_QUERY_CONDITION_LEAF_IN );
+ gda_query_set_condition( query, cond );
+ g_object_unref( G_OBJECT(cond) );
+
+ key = gda_query_field_field_new( query, "account_guid" );
+ gda_query_field_set_visible( key, TRUE );
+ gda_query_condition_leaf_set_operator( cond,
+ GDA_QUERY_CONDITION_OP_LEFT,
+ GDA_QUERY_FIELD(key) );
+ g_object_unref( G_OBJECT(key) );
+
+ key_value = gda_query_field_value_new( query, G_TYPE_STRING );
+ gda_query_field_set_visible( key_value, TRUE );
+ gda_query_field_value_set_is_parameter( GDA_QUERY_FIELD_VALUE(key_value), TRUE );
+
+ g_object_set( key_value, "value-provider", subQuery, NULL );
+ gda_query_condition_leaf_set_operator( cond, GDA_QUERY_CONDITION_OP_RIGHT,
+ GDA_QUERY_FIELD(key_value) );
+
+ return query;
+#endif
+#endif
+}
+
+static void
+run_split_query( GncGdaBackend* be, gpointer pQuery )
+{
+ GdaQuery* query;
+#if 1
+ const gchar* sql = (const gchar*)pQuery;
+
+ query = gnc_gda_create_query_from_sql( be, sql );
+#else
+ query = GDA_QUERY(pQuery);
+#endif
+ query_transactions( be, query );
+}
+
+static void
+free_split_query( GncGdaBackend* pBackend, gpointer pQuery )
+{
+#if 1
+ g_free( pQuery );
+#else
+ g_object_unref( G_OBJECT(pQuery) );
+#endif
+}
+
+/* ================================================================= */
+void
+gnc_gda_init_transaction_handler( void )
+{
+ static GncGdaDataType_t be_data_tx =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_TRANS,
+ gnc_gda_save_transaction, /* commit */
+ NULL, /* initial_load */
+ create_transaction_tables /* create tables */
+ };
+ static GncGdaDataType_t be_data_split =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_SPLIT,
+ commit_split, /* commit */
+ NULL, /* initial_load */
+ NULL, /* create tables */
+ compile_split_query,
+ run_split_query,
+ free_split_query
+ };
+
+ qof_object_register_backend( GNC_ID_TRANS, GNC_GDA_BACKEND, &be_data_tx );
+ qof_object_register_backend( GNC_ID_SPLIT, GNC_GDA_BACKEND, &be_data_split );
+}
+
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/backend/gda/gnc-transaction-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gnc-transaction-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gnc-transaction-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,43 @@
+/********************************************************************
+ * gnc-transaction-gda.h: load and save data to SQL via libgda *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+/** @file gnc-transaction-gda.h
+ * @brief load and save data to SQL via libgda
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_TRANSACTION_GDA_H_
+#define GNC_TRANSACTION_GDA_H_
+
+#include "qof.h"
+#include <gmodule.h>
+
+void gnc_gda_init_transaction_handler( void );
+void gnc_gda_transaction_commit_splits( GncGdaBackend* be, Transaction* pTx );
+void gnc_gda_save_transaction( GncGdaBackend* be, QofInstance* inst );
+void gnc_gda_get_account_balances( GncGdaBackend* be, Account* pAccount,
+ gnc_numeric* start_balance,
+ gnc_numeric* cleared_balance,
+ gnc_numeric* reconciled_balance );
+
+#endif /* GNC_TRANSACTION_GDA_H_ */
Added: gnucash/branches/gda-dev2/src/backend/gda/gncmod-backend-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/gncmod-backend-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/gncmod-backend-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,63 @@
+/*********************************************************************
+ * gncmod-backend-gda.c
+ * module definition/initialization for the gda backend module
+ *
+ * Copyright (c) 2001 Linux Developers Group, Inc.
+ *********************************************************************/
+
+#include <stdio.h>
+#include <gmodule.h>
+/* #include <glib-gobject.h> */
+
+#include "gnc-module.h"
+#include "gnc-module-api.h"
+
+/* version of the gnc module system interface we require */
+int gnc_module_system_interface = 0;
+
+/* module versioning uses libtool semantics. */
+int gnc_module_current = 0;
+int gnc_module_revision = 0;
+int gnc_module_age = 0;
+
+static GNCModule engine;
+
+gchar *
+gnc_module_path(void)
+{
+ return g_strdup("gnucash/backend/gda");
+}
+
+gchar *
+gnc_module_description(void)
+{
+ return g_strdup("The GDA/SQL backend for GnuCash");
+}
+
+int
+gnc_module_init(int refcount)
+{
+ engine = gnc_module_load("gnucash/engine", 0);
+ if(!engine) return FALSE;
+
+ /* Need to initialize g-type engine for gconf */
+ if (refcount == 0) {
+ g_type_init();
+ }
+
+ return TRUE;
+}
+
+int
+gnc_module_end(int refcount)
+{
+ int unload = TRUE;
+
+ if (engine)
+ unload = gnc_module_unload(engine);
+
+ if (refcount == 0)
+ engine = NULL;
+
+ return unload;
+}
Added: gnucash/branches/gda-dev2/src/backend/gda/test/Makefile.am
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/test/Makefile.am (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/test/Makefile.am 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,48 @@
+SUBDIRS = .
+
+TESTS = \
+ test-load-backend
+
+GNC_TEST_DEPS := \
+ --gnc-module-dir ${top_builddir}/src/engine \
+ --guile-load-dir ${top_builddir}/src/engine \
+ --library-dir ${top_builddir}/lib/libqof/qof \
+ --library-dir ${top_builddir}/src/core-utils \
+ --library-dir ${top_builddir}/src/gnc-module \
+ --library-dir ${top_builddir}/src/engine \
+ --library-dir ${top_builddir}/src/backend/gda
+
+TESTS_ENVIRONMENT := \
+ GNC_ACCOUNT_PATH=${top_srcdir}/accounts/C \
+ SRCDIR=${srcdir} \
+ $(shell ${top_srcdir}/src/gnc-test-env --no-exports ${GNC_TEST_DEPS})
+
+check_PROGRAMS = \
+ test-load-backend
+
+#noinst_HEADERS = test-file-stuff.h
+
+LDADD = ${top_builddir}/src/test-core/libgncmod-test.la \
+ ${top_builddir}/src/gnc-module/libgnc-module.la \
+ ${top_builddir}/src/engine/libgncmod-engine.la \
+ ${top_builddir}/src/engine/test-core/libgncmod-test-engine.la \
+ ${top_builddir}/src/core-utils/libgnc-core-utils.la \
+ ${QOF_LIBS} \
+ ${top_builddir}/lib/libc/libc-missing.la
+
+AM_CFLAGS = \
+ -I${top_srcdir}/lib/libc \
+ -I${top_srcdir}/src \
+ -I${top_srcdir}/src/core-utils \
+ -I${top_srcdir}/src/gnc-module \
+ -I${top_srcdir}/src/test-core \
+ -I${top_srcdir}/src/engine \
+ -I${top_srcdir}/src/engine/test-core \
+ -I${top_srcdir}/src/backend/gda \
+ -I${top_srcdir}/src/backend/qsf \
+ ${GLIB_CFLAGS} \
+ ${QOF_CFLAGS} \
+ ${GUILE_INCS} \
+ ${GCONF_CFLAGS}
+
+INCLUDES = -DG_LOG_DOMAIN=\"gnc.backend.gda\"
Added: gnucash/branches/gda-dev2/src/backend/gda/test/test-load-backend.c
===================================================================
--- gnucash/branches/gda-dev2/src/backend/gda/test/test-load-backend.c (rev 0)
+++ gnucash/branches/gda-dev2/src/backend/gda/test/test-load-backend.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * test-load-backend.c
+ *
+ * Replaces the guile version to test the GModule file backend loading.
+ *
+ * Sun Oct 9 18:58:47 2005
+ * Copyright 2005 Neil Williams
+ * linux at codehelp.co.uk
+ ****************************************************************************/
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "qof.h"
+#include "cashobjects.h"
+#include "test-stuff.h"
+
+#define GNC_LIB_NAME "gncmod-backend-gda"
+
+int main (int argc, char ** argv)
+{
+ qof_init();
+ cashobjects_register();
+ do_test(
+ qof_load_backend_library ("../.libs/", GNC_LIB_NAME),
+ " loading gnc-backend-gda GModule failed");
+ print_test_results();
+ qof_close();
+ exit(get_rv());
+}
Copied: gnucash/branches/gda-dev2/src/backend/xml (from rev 16699, gnucash/branches/gda-dev2/src/backend/file)
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/Makefile.am
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/Makefile.am (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/Makefile.am 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,54 @@
+SUBDIRS = .
+
+pkglib_LTLIBRARIES = libgncmod-business-backend-gda.la
+
+AM_CFLAGS = \
+ -I${top_srcdir}/src \
+ -I${top_srcdir}/src/backend \
+ -I${top_srcdir}/src/backend/gda \
+ -I${top_srcdir}/src/engine \
+ -I${top_srcdir}/src/gnc-module \
+ -I${top_srcdir}/src/business/business-core \
+ ${QOF_CFLAGS} \
+ ${GLIB_CFLAGS} \
+ ${LIBGDA_CFLAGS}
+
+libgncmod_business_backend_gda_la_SOURCES = \
+ gncmod-business-backend-gda.c \
+ gnc-address-gda.c \
+ gnc-bill-term-gda.c \
+ gnc-customer-gda.c \
+ gnc-employee-gda.c \
+ gnc-entry-gda.c \
+ gnc-invoice-gda.c \
+ gnc-job-gda.c \
+ gnc-order-gda.c \
+ gnc-vendor-gda.c
+
+#libgncmod_business_backend_gda_la_SOURCES = \
+# gnc-owner-gda.c \
+# gnc-tax-table-gda.c
+
+noinst_HEADERS = \
+ gnc-address-gda.h \
+ gnc-bill-term-gda.h \
+ gnc-customer-gda.h \
+ gnc-employee-gda.h \
+ gnc-entry-gda.h \
+ gnc-invoice-gda.h \
+ gnc-job-gda.h \
+ gnc-order-gda.h \
+ gnc-owner-gda.h \
+ gnc-tax-table-gda.h \
+ gnc-vendor-gda.h
+
+libgncmod_business_backend_gda_la_LDFLAGS = -module -avoid-version
+
+libgncmod_business_backend_gda_la_LIBADD = \
+ ${top_builddir}/src/business/business-core/libgncmod-business-core.la \
+ ${top_builddir}/src/backend/gda/libgnc-backend-gda-utils.la \
+ ${top_builddir}/src/engine/libgncmod-engine.la \
+ ${top_builddir}/src/gnc-module/libgnc-module.la \
+ ${QOF_LIBS} \
+ ${GLIB_LIBS} \
+ ${LIBGDA_LIBS}
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-address-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-address-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-address-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,226 @@
+/********************************************************************\
+ * gnc-address-gda.c -- address gda backend implementation *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @file gnc-address-gda.c
+ * @brief load and save address data to SQL via libgda
+ * @author Copyright (c) 2007 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libgda/libgda.h>
+
+#include "gnc-engine.h"
+#include "gnc-address-gda.h"
+
+#include "gnc-backend-util-gda.h"
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define ADDRESS_MAX_NAME_LEN 50
+#define ADDRESS_MAX_ADDRESS_LINE_LEN 50
+#define ADDRESS_MAX_PHONE_LEN 40
+#define ADDRESS_MAX_FAX_LEN 40
+#define ADDRESS_MAX_EMAIL_LEN 40
+
+static col_cvt_t col_table[] =
+{
+ { "name", CT_STRING, ADDRESS_MAX_NAME_LEN, COL_NNUL, NULL, ADDRESS_NAME },
+ { "addr1", CT_STRING, ADDRESS_MAX_ADDRESS_LINE_LEN, COL_NNUL, NULL, ADDRESS_ONE },
+ { "addr2", CT_STRING, ADDRESS_MAX_ADDRESS_LINE_LEN, COL_NNUL, NULL, ADDRESS_TWO },
+ { "addr3", CT_STRING, ADDRESS_MAX_ADDRESS_LINE_LEN, COL_NNUL, NULL, ADDRESS_THREE },
+ { "addr4", CT_STRING, ADDRESS_MAX_ADDRESS_LINE_LEN, COL_NNUL, NULL, ADDRESS_FOUR },
+ { "phone", CT_STRING, ADDRESS_MAX_PHONE_LEN, COL_NNUL, NULL, ADDRESS_PHONE },
+ { "fax", CT_STRING, ADDRESS_MAX_FAX_LEN, COL_NNUL, NULL, ADDRESS_FAX },
+ { "email", CT_STRING, ADDRESS_MAX_EMAIL_LEN, COL_NNUL, NULL, ADDRESS_EMAIL },
+ { NULL }
+};
+
+typedef void (*AddressSetterFunc)( gpointer, GncAddress* );
+typedef GncAddress* (*AddressGetterFunc)( const gpointer );
+
+static void
+load_address( const GncGdaBackend* be, GdaDataModel* pModel, gint row,
+ QofSetterFunc setter, gpointer pObject,
+ const col_cvt_t* table )
+{
+ const GValue* val;
+ gchar* buf;
+ GncAddress* addr;
+ AddressSetterFunc a_setter = (AddressSetterFunc)setter;
+ const col_cvt_t* subtable;
+ const gchar* s;
+
+ addr = gncAddressCreate( be->primary_book, NULL );
+ for( subtable = col_table; subtable->col_name != NULL; subtable++ ) {
+ buf = g_strdup_printf( "%s_%s", table->col_name, subtable->col_name );
+ val = gda_data_model_get_value_at_col_name( pModel, buf, row );
+ g_free( buf );
+ if( gda_value_is_null( val ) ) {
+ s = NULL;
+ } else {
+ s = g_value_get_string( val );
+ }
+ if( subtable->gobj_param_name != NULL ) {
+ g_object_set( addr, subtable->gobj_param_name, s, NULL );
+ } else {
+ if( subtable->param_name != NULL ) {
+ setter = qof_class_get_parameter_setter( GNC_ID_ADDRESS, subtable->param_name );
+ } else {
+ setter = subtable->setter;
+ }
+ (*setter)( addr, (const gpointer)s );
+ }
+ }
+ (*a_setter)( pObject, addr );
+}
+
+static void
+get_gvalue_address( const GncGdaBackend* be, QofIdTypeConst obj_name, const gpointer pObject,
+ const col_cvt_t* table_row, GValue* value )
+{
+ AddressGetterFunc getter;
+ GncAddress* addr;
+
+ memset( value, 0, sizeof( GValue ) );
+
+ getter = (AddressGetterFunc)gnc_gda_get_getter( obj_name, table_row );
+ addr = (*getter)( pObject );
+ g_value_init( value, gnc_address_get_type() );
+ g_value_set_object( value, addr );
+}
+
+static void
+get_gvalue_address_for_query( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+ GValue subfield_value;
+ GncAddress* addr;
+ gchar* s;
+ QofAccessFunc getter;
+ const col_cvt_t* subtable_row;
+ gchar* buf;
+
+ memset( &value, 0, sizeof( GValue ) );
+ get_gvalue_address( be, obj_name, pObject, table_row, &value );
+
+ if( G_VALUE_TYPE(&value) != 0 ) {
+ addr = g_value_get_object( &value );
+ for( subtable_row = col_table; subtable_row->col_name != NULL; subtable_row++ ) {
+ buf = g_strdup_printf( "%s_%s", table_row->col_name, subtable_row->col_name );
+
+ memset( &subfield_value, 0, sizeof( GValue ) );
+ if( subtable_row->gobj_param_name != NULL ) {
+ g_object_get( addr, subtable_row->gobj_param_name, &s, NULL );
+ } else {
+ getter = gnc_gda_get_getter( GNC_ID_ADDRESS, subtable_row );
+ s = (gchar*)(*getter)( addr, NULL );
+ }
+ if( s ) {
+ g_value_init( &subfield_value, G_TYPE_STRING );
+ g_value_set_string( &subfield_value, s );
+ }
+ gnc_gda_add_field_to_query( query, buf, &subfield_value );
+ g_free( buf );
+ }
+ }
+}
+
+static GdaQueryCondition*
+get_gvalue_address_cond( const GncGdaBackend* be, QofIdTypeConst obj_name,
+ const gpointer pObject, const col_cvt_t* table_row, GdaQuery* query )
+{
+ GValue value;
+ GValue subfield_value;
+ GncAddress* addr;
+ gchar* buf;
+ GdaQueryCondition* sub_cond;
+ GdaQueryCondition* cond;
+ const col_cvt_t* subtable_row;
+ gchar* s;
+ QofAccessFunc getter;
+
+ memset( &value, 0, sizeof( GValue ) );
+ get_gvalue_address( be, obj_name, pObject, table_row, &value );
+
+ cond = gda_query_condition_new( query, GDA_QUERY_CONDITION_NODE_AND );
+ if( G_VALUE_TYPE(&value) != 0 ) {
+ addr = g_value_get_object( &value );
+ for( subtable_row = col_table; subtable_row->col_name != NULL; subtable_row++ ) {
+ buf = g_strdup_printf( "%s_%s", table_row->col_name, subtable_row->col_name );
+
+ memset( &subfield_value, 0, sizeof( GValue ) );
+ if( subtable_row->gobj_param_name != NULL ) {
+ g_object_get( addr, subtable_row->gobj_param_name, &s, NULL );
+ } else {
+ getter = gnc_gda_get_getter( GNC_ID_ADDRESS, subtable_row );
+ s = (gchar*)(*getter)( addr, NULL );
+ }
+ if( s ) {
+ g_value_init( &subfield_value, G_TYPE_STRING );
+ g_value_set_string( &subfield_value, s );
+ }
+ sub_cond = gnc_gda_create_condition_from_field( query, buf, &subfield_value );
+ gda_query_condition_node_add_child( cond, sub_cond, NULL );
+ g_free( buf );
+ }
+ }
+
+ return cond;
+}
+
+static void
+create_address_col( GdaServerProvider* server, GdaConnection* cnn,
+ xmlNodePtr array_data, const col_cvt_t* table_row, gboolean pkey )
+{
+ const gchar* dbms_type;
+ gchar* buf;
+ const col_cvt_t* subtable_row;
+
+ dbms_type = gda_server_provider_get_default_dbms_type( server, cnn,
+ G_TYPE_STRING );
+ for( subtable_row = col_table; subtable_row->col_name != NULL; subtable_row++ ) {
+ buf = g_strdup_printf( "%s_%s", table_row->col_name, subtable_row->col_name );
+ gnc_gda_add_table_column( server, cnn, array_data, buf, dbms_type, subtable_row->size, subtable_row->flags );
+ g_free( buf );
+ }
+}
+
+static col_type_handler_t address_handler =
+ { load_address, create_address_col,
+ get_gvalue_address_for_query, get_gvalue_address_cond };
+
+/* ================================================================= */
+void
+gnc_address_gda_initialize( void )
+{
+ gnc_gda_register_col_type_handler( CT_ADDRESS, &address_handler );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-address-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-address-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-address-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,38 @@
+/* gnc-address-gda.h -- Address GDA header
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ */
+
+/** @file gnc-address-gda.h
+ * @brief load and save address data to SQL via libgda
+ * @author Copyright (c) 2007 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_ADDRESS_GDA_H
+#define GNC_ADDRESS_GDA_H
+
+#include "gncAddress.h"
+
+#define CT_ADDRESS "address"
+
+void gnc_address_gda_initialize( void );
+
+#endif /* GNC_ADDRESS_GDA_H */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-bill-term-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-bill-term-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-bill-term-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,205 @@
+/********************************************************************\
+ * gnc-bill-term-gda.c -- billing term gda backend *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+#include "config.h"
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libgda/libgda.h>
+
+#include "gnc-backend-util-gda.h"
+
+#include "gncBillTermP.h"
+#include "gncInvoice.h"
+#include "gnc-bill-term-gda.h"
+#include "qof.h"
+
+#define _GNC_MOD_NAME GNC_ID_BILLTERM
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define MAX_NAME_LEN 50
+#define MAX_DESCRIPTION_LEN 50
+#define MAX_TYPE_LEN 50
+
+static void set_invisible( gpointer data, gpointer value );
+
+#define TABLE_NAME "billterms"
+
+static col_cvt_t col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "name", CT_STRING, MAX_NAME_LEN, COL_NNUL, NULL, GNC_BILLTERM_NAME },
+ { "description", CT_STRING, MAX_DESCRIPTION_LEN, COL_NNUL, NULL, GNC_BILLTERM_DESC },
+ { "refcount", CT_INT, 0, COL_NNUL, NULL, GNC_BILLTERM_REFCOUNT },
+ { "invisible", CT_BOOLEAN, 0, COL_NNUL, NULL, NULL,
+ (QofAccessFunc)gncBillTermGetInvisible, (QofSetterFunc)set_invisible },
+ { "parent", CT_BILLTERMREF, 0, 0, NULL, NULL,
+ (QofAccessFunc)gncBillTermGetParent, (QofSetterFunc)gncBillTermSetParent },
+ { "child", CT_BILLTERMREF, 0, 0, NULL, NULL,
+ (QofAccessFunc)gncBillTermReturnChild, (QofSetterFunc)gncBillTermSetChild },
+ { "type", CT_STRING, MAX_TYPE_LEN, COL_NNUL, NULL, GNC_BILLTERM_TYPE },
+ { "duedays", CT_INT, 0, 0, 0, GNC_BILLTERM_DUEDAYS },
+ { "discountdays", CT_INT, 0, 0, 0, GNC_BILLTERM_DISCDAYS },
+ { "discount", CT_NUMERIC, 0, 0, 0, GNC_BILLTERM_DISCOUNT },
+ { "cutoff", CT_INT, 0, 0, 0, GNC_BILLTERM_CUTOFF },
+ { NULL }
+};
+
+static void
+set_invisible( gpointer data, gpointer value )
+{
+ GncBillTerm* term = GNC_BILLTERM(data);
+ gboolean b = GPOINTER_TO_INT(value);
+
+ if( b ) {
+ gncBillTermMakeInvisible( term );
+ }
+}
+
+static GncBillTerm*
+load_single_billterm( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ const GUID* guid;
+ GUID v_guid;
+ GncBillTerm* pBillTerm;
+
+ guid = gnc_gda_load_guid( be, pModel, row );
+ v_guid = *guid;
+
+ pBillTerm = gncBillTermLookup( be->primary_book, &v_guid );
+ if( pBillTerm == NULL ) {
+ pBillTerm = gncBillTermCreate( be->primary_book );
+ }
+ gnc_gda_load_object( be, pModel, row, GNC_ID_BILLTERM, pBillTerm, col_table );
+ gnc_gda_slots_load( be, qof_instance_get_guid( QOF_INSTANCE( pBillTerm )),
+ qof_instance_get_slots( QOF_INSTANCE(pBillTerm) ) );
+
+ qof_instance_mark_clean( QOF_INSTANCE(pBillTerm) );
+
+ return pBillTerm;
+}
+
+static void
+load_all_billterms( GncGdaBackend* be )
+{
+ static GdaQuery* query = NULL;
+ GdaObject* ret;
+ QofBook* pBook = be->primary_book;
+
+ /* First time, create the query */
+ if( query == NULL ) {
+ query = gnc_gda_create_select_query( be, TABLE_NAME );
+ }
+
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+
+ for( r = 0; r < numRows; r++ ) {
+ (void)load_single_billterm( be, pModel, r );
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_billterm_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, TABLE_NAME, col_table );
+}
+
+/* ================================================================= */
+void
+gnc_gda_save_billterm( GncGdaBackend* be, QofInstance* inst )
+{
+ GncBillTerm* v = GNC_BILLTERM(inst);
+ const GUID* guid;
+
+ (void)gnc_gda_do_db_operation( be,
+ (qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+ TABLE_NAME,
+ GNC_ID_BILLTERM, v,
+ col_table );
+
+ // Now, commit or delete any slots
+ guid = qof_instance_get_guid( inst );
+ if( !qof_instance_get_destroying(inst) ) {
+ gnc_gda_slots_save( be, guid, qof_instance_get_slots( inst ) );
+ } else {
+ gnc_gda_slots_delete( be, guid );
+ }
+}
+
+/* ================================================================= */
+static void
+load_billterm_guid( const GncGdaBackend* be, GdaDataModel* pModel, gint row,
+ QofSetterFunc setter, gpointer pObject,
+ const col_cvt_t* table )
+{
+ const GValue* val;
+ GUID guid;
+ const GUID* pGuid;
+ GncBillTerm* term = NULL;
+
+ 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;
+ }
+ if( pGuid != NULL ) {
+ term = gncBillTermLookup( be->primary_book, pGuid );
+ }
+ if( table->gobj_param_name != NULL ) {
+ g_object_set( pObject, table->gobj_param_name, term, NULL );
+ } else {
+ (*setter)( pObject, (const gpointer)term );
+ }
+}
+
+static col_type_handler_t billterm_guid_handler =
+ { load_billterm_guid, gnc_gda_create_objectref_guid_col,
+ gnc_gda_get_gvalue_objectref_guid_for_query, gnc_gda_get_gvalue_objectref_guid_cond };
+/* ================================================================= */
+void
+gnc_billterm_gda_initialize( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_BILLTERM,
+ gnc_gda_save_billterm, /* commit */
+ load_all_billterms, /* initial_load */
+ create_billterm_tables /* create_tables */
+ };
+
+ qof_object_register_backend( GNC_ID_BILLTERM, GNC_GDA_BACKEND, &be_data );
+
+ gnc_gda_register_col_type_handler( CT_BILLTERMREF, &billterm_guid_handler );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-bill-term-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-bill-term-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-bill-term-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,39 @@
+/*
+ * gnc-bill-term-gda.h -- billing term gda backend
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ */
+
+/** @file gnc-bill-term-gda.h
+ * @brief load and save accounts data to SQL via libgda
+ * @author Copyright (c) 2006 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_BILLTERM_GDA_H
+#define GNC_BILLTERM_GDA_H
+
+#include "gncBillTerm.h"
+
+#define CT_BILLTERMREF "billterm"
+
+void gnc_billterm_gda_initialize( void );
+
+#endif /* GNC_BILLTERM_GDA_H */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-customer-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-customer-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-customer-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,163 @@
+/********************************************************************\
+ * gnc-customer-gda.c -- customer gda backend *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+#include "config.h"
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libgda/libgda.h>
+
+#include "gnc-backend-util-gda.h"
+
+#include "gncBillTermP.h"
+#include "gncCustomerP.h"
+#include "gncTaxTableP.h"
+#include "gnc-customer-gda.h"
+#include "gnc-address-gda.h"
+#include "gnc-bill-term-gda.h"
+
+#define _GNC_MOD_NAME GNC_ID_CUSTOMER
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define TABLE_NAME "customers"
+
+#define MAX_NAME_LEN 50
+#define MAX_ID_LEN 50
+#define MAX_NOTES_LEN 50
+
+static col_cvt_t col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "name", CT_STRING, MAX_NAME_LEN, COL_NNUL, NULL, CUSTOMER_NAME },
+ { "id", CT_STRING, MAX_ID_LEN, COL_NNUL, NULL, CUSTOMER_ID },
+ { "notes", CT_STRING, MAX_NOTES_LEN, COL_NNUL, NULL, CUSTOMER_NOTES },
+ { "active", CT_BOOLEAN, 0, COL_NNUL, NULL, QOF_PARAM_ACTIVE },
+ { "discount", CT_NUMERIC, 0, COL_NNUL, NULL, CUSTOMER_DISCOUNT },
+ { "credit", CT_NUMERIC, 0, COL_NNUL, NULL, CUSTOMER_CREDIT },
+ { "currency", CT_COMMODITYREF, 0, COL_NNUL, NULL, NULL,
+ (QofAccessFunc)gncCustomerGetCurrency, (QofSetterFunc)gncCustomerSetCurrency },
+ { "tax_override", CT_BOOLEAN, 0, COL_NNUL, NULL, CUSTOMER_TT_OVER },
+ { "addr", CT_ADDRESS, 0, 0, NULL, CUSTOMER_ADDR },
+ { "shipaddr", CT_ADDRESS, 0, 0, NULL, CUSTOMER_SHIPADDR },
+ { "terms", CT_BILLTERMREF, 0, 0, NULL, CUSTOMER_TERMS },
+ { "tax_included", CT_INT, 0, 0, NULL, NULL,
+ (QofAccessFunc)gncCustomerGetTaxIncluded, (QofSetterFunc)gncCustomerSetTaxIncluded },
+ { "taxtable", CT_TAXTABLEREF, 0, 0, NULL, NULL,
+ (QofAccessFunc)gncCustomerGetTaxTable, (QofSetterFunc)gncCustomerSetTaxTable },
+ { NULL }
+};
+
+static GncCustomer*
+load_single_customer( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ const GUID* guid;
+ GUID customer_guid;
+ GncCustomer* pCustomer;
+
+ guid = gnc_gda_load_guid( be, pModel, row );
+ customer_guid = *guid;
+
+ pCustomer = gncCustomerLookup( be->primary_book, &customer_guid );
+ if( pCustomer == NULL ) {
+ pCustomer = gncCustomerCreate( be->primary_book );
+ }
+ gnc_gda_load_object( be, pModel, row, GNC_ID_CUSTOMER, pCustomer, col_table );
+ gnc_gda_slots_load( be, qof_instance_get_guid( QOF_INSTANCE( pCustomer )),
+ qof_instance_get_slots( QOF_INSTANCE(pCustomer) ) );
+
+ qof_instance_mark_clean( QOF_INSTANCE(pCustomer) );
+
+ return pCustomer;
+}
+
+static void
+load_all_customers( GncGdaBackend* be )
+{
+ static GdaQuery* query = NULL;
+ GdaObject* ret;
+ QofBook* pBook = be->primary_book;
+
+ /* First time, create the query */
+ if( query == NULL ) {
+ query = gnc_gda_create_select_query( be, TABLE_NAME );
+ }
+
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+
+ for( r = 0; r < numRows; r++ ) {
+ (void)load_single_customer( be, pModel, r );
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_customer_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, TABLE_NAME, col_table );
+}
+
+/* ================================================================= */
+void
+gnc_gda_save_customer( GncGdaBackend* be, QofInstance* inst )
+{
+ GncCustomer* customer = GNC_CUSTOMER(inst);
+ const GUID* guid;
+
+ (void)gnc_gda_do_db_operation( be,
+ (qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+ TABLE_NAME,
+ GNC_ID_CUSTOMER, customer,
+ col_table );
+
+ // Now, commit or delete any slots
+ guid = qof_instance_get_guid( inst );
+ if( !qof_instance_get_destroying(inst) ) {
+ gnc_gda_slots_save( be, guid, qof_instance_get_slots( inst ) );
+ } else {
+ gnc_gda_slots_delete( be, guid );
+ }
+}
+
+/* ================================================================= */
+void
+gnc_customer_gda_initialize( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_CUSTOMER,
+ gnc_gda_save_customer, /* commit */
+ load_all_customers, /* initial_load */
+ create_customer_tables /* create_tables */
+ };
+
+ qof_object_register_backend( GNC_ID_CUSTOMER, GNC_GDA_BACKEND, &be_data );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-customer-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-customer-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-customer-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,35 @@
+/*
+ * gnc-customer-gda.h -- customer gda backend
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ */
+
+/** @file gnc-customer-gda.h
+ * @brief load and save customer data to SQL via libgda
+ * @author Copyright (c) 2007 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_CUSTOMER_GDA_H
+#define GNC_CUSTOMER_GDA_H
+
+void gnc_customer_gda_initialize( void );
+
+#endif /* GNC_CUSTOMER_GDA_H */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-employee-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-employee-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-employee-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,163 @@
+/********************************************************************\
+ * gnc-employee-xml-v2.c -- employee xml i/o implementation *
+ * *
+ * Copyright (C) 2002 Derek Atkins <warlord at MIT.EDU> *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+#include "config.h"
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libgda/libgda.h>
+
+#include "gncEmployeeP.h"
+#include "gnc-employee-gda.h"
+#include "gnc-address-gda.h"
+#include "gnc-commodity.h"
+
+#include "gnc-backend-util-gda.h"
+
+#define _GNC_MOD_NAME GNC_ID_EMPLOYEE
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define MAX_USERNAME_LEN 50
+#define MAX_ID_LEN 50
+#define MAX_LANGUAGE_LEN 50
+#define MAX_ACL_LEN 50
+
+#define TABLE_NAME "employees"
+
+static col_cvt_t col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "username", CT_STRING, MAX_USERNAME_LEN, COL_NNUL, NULL, EMPLOYEE_USERNAME },
+ { "id", CT_STRING, MAX_ID_LEN, COL_NNUL, NULL, EMPLOYEE_ID },
+ { "language", CT_STRING, MAX_LANGUAGE_LEN, COL_NNUL, NULL, EMPLOYEE_LANGUAGE },
+ { "acl", CT_STRING, MAX_ACL_LEN, COL_NNUL, NULL, EMPLOYEE_ACL },
+ { "active", CT_BOOLEAN, 0, COL_NNUL, NULL, QOF_PARAM_ACTIVE },
+ { "currency", CT_COMMODITYREF, 0, COL_NNUL, NULL, NULL,
+ (QofAccessFunc)gncEmployeeGetCurrency, (QofSetterFunc)gncEmployeeSetCurrency },
+ { "ccard_guid", CT_ACCOUNTREF, 0, COL_NNUL, NULL, EMPLOYEE_CC },
+ { "workday", CT_NUMERIC, 0, COL_NNUL, NULL, EMPLOYEE_WORKDAY },
+ { "rate", CT_NUMERIC, 0, COL_NNUL, NULL, EMPLOYEE_RATE },
+ { "addr", CT_ADDRESS, 0, 0, NULL, EMPLOYEE_ADDR },
+ { NULL }
+};
+
+static GncEmployee*
+load_single_employee( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ const GUID* guid;
+ GUID emp_guid;
+ GncEmployee* pEmployee;
+
+ guid = gnc_gda_load_guid( be, pModel, row );
+ emp_guid = *guid;
+
+ pEmployee = gncEmployeeLookup( be->primary_book, &emp_guid );
+ if( pEmployee == NULL ) {
+ pEmployee = gncEmployeeCreate( be->primary_book );
+ }
+ gnc_gda_load_object( be, pModel, row, GNC_ID_EMPLOYEE, pEmployee, col_table );
+ gnc_gda_slots_load( be, qof_instance_get_guid( QOF_INSTANCE( pEmployee )),
+ qof_instance_get_slots( QOF_INSTANCE(pEmployee) ) );
+
+ qof_instance_mark_clean( QOF_INSTANCE(pEmployee) );
+
+ return pEmployee;
+}
+
+static void
+load_all_employees( GncGdaBackend* be )
+{
+ static GdaQuery* query = NULL;
+ GdaObject* ret;
+ QofBook* pBook = be->primary_book;
+ gnc_commodity_table* pTable = gnc_commodity_table_get_table( pBook );
+
+ /* First time, create the query */
+ if( query == NULL ) {
+ query = gnc_gda_create_select_query( be, TABLE_NAME );
+ }
+
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+
+ for( r = 0; r < numRows; r++ ) {
+ (void)load_single_employee( be, pModel, r );
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_employee_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, TABLE_NAME, col_table );
+}
+
+/* ================================================================= */
+void
+gnc_gda_save_employee( GncGdaBackend* be, QofInstance* inst )
+{
+ GncEmployee* emp = GNC_EMPLOYEE(inst);
+ const GUID* guid;
+
+ // Ensure the commodity is in the db
+ gnc_gda_save_commodity( be, gncEmployeeGetCurrency( emp ) );
+
+ (void)gnc_gda_do_db_operation( be,
+ (qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+ TABLE_NAME,
+ GNC_ID_EMPLOYEE, emp,
+ col_table );
+
+ // Now, commit or delete any slots
+ guid = qof_instance_get_guid( inst );
+ if( !qof_instance_get_destroying(inst) ) {
+ gnc_gda_slots_save( be, guid, qof_instance_get_slots( inst ) );
+ } else {
+ gnc_gda_slots_delete( be, guid );
+ }
+}
+
+/* ================================================================= */
+void
+gnc_employee_gda_initialize( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_EMPLOYEE,
+ gnc_gda_save_employee, /* commit */
+ load_all_employees, /* initial_load */
+ create_employee_tables /* create_tables */
+ };
+
+ qof_object_register_backend( GNC_ID_EMPLOYEE, GNC_GDA_BACKEND, &be_data );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-employee-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-employee-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-employee-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,35 @@
+/*
+ * gnc-employee-gda.h -- employee gda backend
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ */
+
+/** @file gnc-employee-gda.h
+ * @brief load and save employee data to SQL via libgda
+ * @author Copyright (c) 2007 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_EMPLOYEE_GDA_H
+#define GNC_EMPLOYEE_GDA_H
+
+void gnc_employee_gda_initialize( void );
+
+#endif /* GNC_EMPLOYEE_GDA_H */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-entry-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-entry-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-entry-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,220 @@
+/********************************************************************\
+ * gnc-entry-xml-v2.c -- entry xml i/o implementation *
+ * *
+ * Copyright (C) 2002 Derek Atkins <warlord at MIT.EDU> *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+#include "config.h"
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libgda/libgda.h>
+
+#include "gnc-backend-util-gda.h"
+
+#include "gncEntryP.h"
+#include "gncOrderP.h"
+#include "gncInvoiceP.h"
+#include "gncTaxTableP.h"
+#include "gnc-entry-gda.h"
+#include "gnc-invoice-gda.h"
+#include "gnc-order-gda.h"
+#include "gnc-owner-gda.h"
+#include "gnc-tax-table-gda.h"
+
+#define _GNC_MOD_NAME GNC_ID_ENTRY
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+static gpointer get_date( gpointer pObject, const QofParam* param );
+static void set_date( gpointer pObject, gpointer pValue );
+static gpointer get_date_entered( gpointer pObject, const QofParam* param );
+static void set_date_entered( gpointer pObject, gpointer pValue );
+
+#define TABLE_NAME "entries"
+#define MAX_DESCRIPTION_LEN 50
+#define MAX_ACTION_LEN 50
+#define MAX_NOTES_LEN 50
+#define MAX_DISCTYPE_LEN 50
+#define MAX_DISCHOW_LEN 50
+
+static col_cvt_t col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "date", CT_TIMESPEC, 0, COL_NNUL, NULL, NULL, get_date, set_date },
+ { "entered", CT_TIMESPEC, 0, COL_NNUL, NULL, NULL, get_date_entered, set_date_entered },
+ { "description", CT_STRING, MAX_DESCRIPTION_LEN, 0, NULL, ENTRY_DESC },
+ { "action", CT_STRING, MAX_ACTION_LEN, 0, NULL, ENTRY_ACTION },
+ { "notes", CT_STRING, MAX_NOTES_LEN, 0, NULL, ENTRY_NOTES },
+ { "quantity", CT_NUMERIC, 0, 0, NULL, ENTRY_QTY },
+ { "i_acct", CT_ACCOUNTREF, 0, 0, NULL, ENTRY_IACCT },
+ { "i_price", CT_NUMERIC, 0, 0, NULL, ENTRY_IPRICE },
+ { "i_discount", CT_NUMERIC, 0, 0, NULL, NULL, (QofAccessFunc)gncEntryGetInvDiscount, (QofSetterFunc)gncEntrySetInvDiscount },
+ { "invoice", CT_INVOICEREF, 0, 0, NULL, ENTRY_INVOICE },
+ { "i_disc_type", CT_STRING, MAX_DISCTYPE_LEN, 0, NULL, ENTRY_INV_DISC_TYPE },
+ { "i_disc_how", CT_STRING, MAX_DISCHOW_LEN, 0, NULL, ENTRY_INV_DISC_HOW },
+ { "i_taxable", CT_BOOLEAN, 0, 0, NULL, ENTRY_INV_TAXABLE },
+ { "i_taxincluded", CT_BOOLEAN, 0, 0, NULL, ENTRY_INV_TAX_INC },
+ { "i_taxtable", CT_TAXTABLEREF, 0, 0, NULL, NULL, (QofAccessFunc)gncEntryGetInvTaxTable, (QofSetterFunc)gncEntrySetInvTaxTable },
+ { "b_acct", CT_ACCOUNTREF, 0, 0, NULL, ENTRY_BACCT },
+ { "b_price", CT_NUMERIC, 0, 0, NULL, ENTRY_BPRICE },
+ { "bill", CT_INVOICEREF, 0, 0, NULL, NULL, (QofAccessFunc)gncEntryGetBill, (QofSetterFunc)gncEntrySetBill },
+ { "b_taxable", CT_BOOLEAN, 0, 0, NULL, ENTRY_BILL_TAXABLE },
+ { "b_taxincluded", CT_BOOLEAN, 0, 0, NULL, ENTRY_BILL_TAX_INC },
+ { "b_taxtable", CT_TAXTABLEREF, 0, 0, NULL, NULL, (QofAccessFunc)gncEntryGetBillTaxTable, (QofSetterFunc)gncEntrySetBillTaxTable },
+ { "b_paytype", CT_INT, 0, 0, NULL, NULL, (QofAccessFunc)gncEntryGetBillPayment, (QofSetterFunc)gncEntrySetBillPayment },
+ { "billable", CT_BOOLEAN, 0, 0, NULL, ENTRY_BILLABLE },
+ { "billto", CT_OWNERREF, 0, 0, NULL, ENTRY_BILLTO },
+ { "order", CT_ORDERREF, 0, 0, NULL, NULL, (QofAccessFunc)gncEntryGetOrder, (QofSetterFunc)gncEntrySetOrder },
+ { NULL }
+};
+
+static gpointer
+get_date( gpointer pObject, const QofParam* param )
+{
+ const GncEntry* pEntry = GNC_ENTRY(pObject);
+ static Timespec ts;
+
+ ts = gncEntryGetDate( pEntry );
+ return (gpointer)&ts;
+}
+
+static void
+set_date( gpointer pObject, gpointer pValue )
+{
+ GncEntry* pEntry = GNC_ENTRY(pObject);
+ Timespec* pTS = (Timespec*)pValue;
+
+ gncEntrySetDate( pEntry, *pTS );
+}
+
+static gpointer
+get_date_entered( gpointer pObject, const QofParam* param )
+{
+ const GncEntry* pEntry = GNC_ENTRY(pObject);
+ static Timespec ts;
+
+ ts = gncEntryGetDateEntered( pEntry );
+ return (gpointer)&ts;
+}
+
+static void
+set_date_entered( gpointer pObject, gpointer pValue )
+{
+ GncEntry* pEntry = GNC_ENTRY(pObject);
+ Timespec* pTS = (Timespec*)pValue;
+
+ gncEntrySetDateEntered( pEntry, *pTS );
+}
+
+static GncEntry*
+load_single_entry( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ const GUID* guid;
+ GUID v_guid;
+ GncEntry* pEntry;
+
+ guid = gnc_gda_load_guid( be, pModel, row );
+ v_guid = *guid;
+
+ pEntry = gncEntryLookup( be->primary_book, &v_guid );
+ if( pEntry == NULL ) {
+ pEntry = gncEntryCreate( be->primary_book );
+ }
+ gnc_gda_load_object( be, pModel, row, GNC_ID_ENTRY, pEntry, col_table );
+ gnc_gda_slots_load( be, qof_instance_get_guid( QOF_INSTANCE( pEntry )),
+ qof_instance_get_slots( QOF_INSTANCE(pEntry) ) );
+
+ qof_instance_mark_clean( QOF_INSTANCE(pEntry) );
+
+ return pEntry;
+}
+
+static void
+load_all_entries( GncGdaBackend* be )
+{
+ static GdaQuery* query = NULL;
+ GdaObject* ret;
+ QofBook* pBook = be->primary_book;
+
+ /* First time, create the query */
+ if( query == NULL ) {
+ query = gnc_gda_create_select_query( be, TABLE_NAME );
+ }
+
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+
+ for( r = 0; r < numRows; r++ ) {
+ (void)load_single_entry( be, pModel, r );
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_entry_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, TABLE_NAME, col_table );
+}
+
+/* ================================================================= */
+void
+gnc_gda_save_entry( GncGdaBackend* be, QofInstance* inst )
+{
+ GncEntry* v = GNC_ENTRY(inst);
+ const GUID* guid;
+
+ (void)gnc_gda_do_db_operation( be,
+ (qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+ TABLE_NAME,
+ GNC_ID_ENTRY, v,
+ col_table );
+
+ // Now, commit or delete any slots
+ guid = qof_instance_get_guid( inst );
+ if( !qof_instance_get_destroying(inst) ) {
+ gnc_gda_slots_save( be, guid, qof_instance_get_slots( inst ) );
+ } else {
+ gnc_gda_slots_delete( be, guid );
+ }
+}
+
+/* ================================================================= */
+void
+gnc_entry_gda_initialize( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_ENTRY,
+ gnc_gda_save_entry, /* commit */
+ load_all_entries, /* initial_load */
+ create_entry_tables /* create_tables */
+ };
+
+ qof_object_register_backend( GNC_ID_ENTRY, GNC_GDA_BACKEND, &be_data );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-entry-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-entry-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-entry-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,35 @@
+/*
+ * gnc-entry-gda.h -- entry gda backend
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ */
+
+/** @file gnc-entry-gda.h
+ * @brief load and save entry data to SQL via libgda
+ * @author Copyright (c) 2007 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_ENTRY_GDA_H
+#define GNC_ENTRY_GDA_H
+
+void gnc_entry_gda_initialize( void );
+
+#endif /* GNC_ENTRY_GDA_H */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-invoice-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-invoice-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-invoice-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,235 @@
+/********************************************************************\
+ * gnc-invoice-gda.c - invoice gda backend *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+#include "config.h"
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libgda/libgda.h>
+
+#include "gnc-backend-util-gda.h"
+
+#include "gncBillTermP.h"
+#include "gncInvoiceP.h"
+#include "gnc-invoice-gda.h"
+#include "gnc-owner-gda.h"
+#include "gnc-bill-term-gda.h"
+
+#define _GNC_MOD_NAME GNC_ID_INVOICE
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define TABLE_NAME "invoices"
+
+#define MAX_ID_LEN 50
+#define MAX_NOTES_LEN 100
+
+static col_cvt_t col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "id", CT_STRING, MAX_ID_LEN, COL_NNUL, NULL, INVOICE_ID },
+ { "date_opened", CT_TIMESPEC, 0, COL_NNUL, NULL, INVOICE_OPENED },
+ { "date_posted", CT_TIMESPEC, 0, 0, NULL, INVOICE_POSTED },
+ { "notes", CT_STRING, MAX_NOTES_LEN, COL_NNUL, NULL, INVOICE_NOTES },
+ { "active", CT_BOOLEAN, 0, COL_NNUL, NULL, QOF_PARAM_ACTIVE },
+ { "currency", CT_COMMODITYREF, 0, COL_NNUL, NULL, NULL,
+ (QofAccessFunc)gncInvoiceGetCurrency, (QofSetterFunc)gncInvoiceSetCurrency },
+ { NULL }
+};
+
+#if 0
+/* ids */
+
+#define invoice_owner_string "invoice:owner"
+#define invoice_terms_string "invoice:terms"
+#define invoice_billing_id_string "invoice:billing_id"
+#define invoice_posttxn_string "invoice:posttxn"
+#define invoice_postlot_string "invoice:postlot"
+#define invoice_postacc_string "invoice:postacc"
+#define invoice_billto_string "invoice:billto"
+#define invoice_tochargeamt_string "invoice:charge-amt"
+
+ xmlAddChild(ret, gnc_owner_to_dom_tree (invoice_owner_string,
+ gncInvoiceGetOwner (invoice)));
+
+ term = gncInvoiceGetTerms (invoice);
+ if (term)
+ xmlAddChild(ret, guid_to_dom_tree(invoice_terms_string,
+ qof_instance_get_guid (QOF_INSTANCE(term))));
+
+ maybe_add_string (ret, invoice_billing_id_string,
+ gncInvoiceGetBillingID (invoice));
+
+ txn = gncInvoiceGetPostedTxn (invoice);
+ if (txn)
+ xmlAddChild (ret, guid_to_dom_tree (invoice_posttxn_string,
+ xaccTransGetGUID (txn)));
+
+ lot = gncInvoiceGetPostedLot (invoice);
+ if (lot)
+ xmlAddChild (ret, guid_to_dom_tree (invoice_postlot_string,
+ gnc_lot_get_guid (lot)));
+
+ acc = gncInvoiceGetPostedAcc (invoice);
+ if (acc)
+ xmlAddChild (ret, guid_to_dom_tree (invoice_postacc_string,
+ qof_instance_get_guid(QOF_INSTANCE(acc))));
+
+ billto = gncInvoiceGetBillTo (invoice);
+ if (billto && billto->owner.undefined != NULL)
+ xmlAddChild (ret, gnc_owner_to_dom_tree (invoice_billto_string, billto));
+
+ amt = gncInvoiceGetToChargeAmount (invoice);
+ if (! gnc_numeric_zero_p (amt))
+ xmlAddChild (ret, gnc_numeric_to_dom_tree (invoice_tochargeamt_string, &amt));
+#endif
+
+static GncInvoice*
+load_single_invoice( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ const GUID* guid;
+ GUID v_guid;
+ GncInvoice* pInvoice;
+
+ guid = gnc_gda_load_guid( be, pModel, row );
+ v_guid = *guid;
+
+ pInvoice = gncInvoiceLookup( be->primary_book, &v_guid );
+ if( pInvoice == NULL ) {
+ pInvoice = gncInvoiceCreate( be->primary_book );
+ }
+ gnc_gda_load_object( be, pModel, row, GNC_ID_INVOICE, pInvoice, col_table );
+ gnc_gda_slots_load( be, qof_instance_get_guid( QOF_INSTANCE( pInvoice )),
+ qof_instance_get_slots( QOF_INSTANCE(pInvoice) ) );
+
+ qof_instance_mark_clean( QOF_INSTANCE(pInvoice) );
+
+ return pInvoice;
+}
+
+static void
+load_all_invoices( GncGdaBackend* be )
+{
+ static GdaQuery* query = NULL;
+ GdaObject* ret;
+ QofBook* pBook = be->primary_book;
+
+ /* First time, create the query */
+ if( query == NULL ) {
+ query = gnc_gda_create_select_query( be, TABLE_NAME );
+ }
+
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+
+ for( r = 0; r < numRows; r++ ) {
+ (void)load_single_invoice( be, pModel, r );
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_invoice_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, TABLE_NAME, col_table );
+}
+
+/* ================================================================= */
+void
+gnc_gda_save_invoice( GncGdaBackend* be, QofInstance* inst )
+{
+ GncInvoice* v = GNC_INVOICE(inst);
+ const GUID* guid;
+
+ // Ensure the commodity is in the db
+ gnc_gda_save_commodity( be, gncInvoiceGetCurrency( v ) );
+
+ (void)gnc_gda_do_db_operation( be,
+ (qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+ TABLE_NAME,
+ GNC_ID_INVOICE, v,
+ col_table );
+
+ // Now, commit or delete any slots
+ guid = qof_instance_get_guid( inst );
+ if( !qof_instance_get_destroying(inst) ) {
+ gnc_gda_slots_save( be, guid, qof_instance_get_slots( inst ) );
+ } else {
+ gnc_gda_slots_delete( be, guid );
+ }
+}
+
+/* ================================================================= */
+static void
+load_invoice_guid( const GncGdaBackend* be, GdaDataModel* pModel, gint row,
+ QofSetterFunc setter, gpointer pObject,
+ const col_cvt_t* table )
+{
+ const GValue* val;
+ GUID guid;
+ const GUID* pGuid;
+ GncInvoice* invoice = NULL;
+
+ 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;
+ }
+ if( pGuid != NULL ) {
+ invoice = gncInvoiceLookup( be->primary_book, pGuid );
+ }
+ if( table->gobj_param_name != NULL ) {
+ g_object_set( pObject, table->gobj_param_name, invoice, NULL );
+ } else {
+ (*setter)( pObject, (const gpointer)invoice );
+ }
+}
+
+static col_type_handler_t invoice_guid_handler =
+ { load_invoice_guid, gnc_gda_create_objectref_guid_col,
+ gnc_gda_get_gvalue_objectref_guid_for_query, gnc_gda_get_gvalue_objectref_guid_cond };
+/* ================================================================= */
+void
+gnc_invoice_gda_initialize( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_INVOICE,
+ gnc_gda_save_invoice, /* commit */
+ load_all_invoices, /* initial_load */
+ create_invoice_tables /* create_tables */
+ };
+
+ qof_object_register_backend( GNC_ID_INVOICE, GNC_GDA_BACKEND, &be_data );
+
+ gnc_gda_register_col_type_handler( CT_INVOICEREF, &invoice_guid_handler );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-invoice-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-invoice-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-invoice-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,37 @@
+/*
+ * gnc-invoice-gda.h -- invoice gda backend
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ */
+
+/** @file gnc-invoice-gda.h
+ * @brief load and save invoice data to SQL via libgda
+ * @author Copyright (c) 2007 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_INVOICE_GDA_H
+#define GNC_INVOICE_GDA_H
+
+#define CT_INVOICEREF "invoice"
+
+void gnc_invoice_gda_initialize( void );
+
+#endif /* GNC_INVOICE_GDA_H */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-job-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-job-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-job-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,156 @@
+/********************************************************************\
+ * gnc-job-gda.c -- job gda backend *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+#include "config.h"
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libgda/libgda.h>
+
+#include "gnc-backend-util-gda.h"
+
+#include "gncJobP.h"
+#include "gnc-job-gda.h"
+#include "gnc-owner-gda.h"
+
+#define _GNC_MOD_NAME GNC_ID_JOB
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define TABLE_NAME "jobs"
+
+#define MAX_ID_LEN 50
+#define MAX_NAME_LEN 50
+#define MAX_REFERENCE_LEN 50
+
+#if 0
+/* ids */
+#define job_owner_string "job:owner"
+
+ xmlAddChild(ret, gnc_owner_to_dom_tree (job_owner_string,
+ gncJobGetOwner (job)));
+#endif
+
+static col_cvt_t col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "id", CT_STRING, MAX_ID_LEN, COL_NNUL, NULL, JOB_ID },
+ { "name", CT_STRING, MAX_NAME_LEN, COL_NNUL, NULL, JOB_NAME },
+ { "reference", CT_STRING, MAX_REFERENCE_LEN, COL_NNUL, NULL, JOB_REFERENCE },
+ { "active", CT_BOOLEAN, 0, COL_NNUL, NULL, JOB_ACTIVE },
+ { NULL }
+};
+
+static GncJob*
+load_single_job( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ const GUID* guid;
+ GUID job_guid;
+ GncJob* pJob;
+
+ guid = gnc_gda_load_guid( be, pModel, row );
+ job_guid = *guid;
+
+ pJob = gncJobLookup( be->primary_book, &job_guid );
+ if( pJob == NULL ) {
+ pJob = gncJobCreate( be->primary_book );
+ }
+ gnc_gda_load_object( be, pModel, row, GNC_ID_JOB, pJob, col_table );
+ gnc_gda_slots_load( be, qof_instance_get_guid( QOF_INSTANCE( pJob )),
+ qof_instance_get_slots( QOF_INSTANCE(pJob) ) );
+
+ qof_instance_mark_clean( QOF_INSTANCE(pJob) );
+
+ return pJob;
+}
+
+static void
+load_all_jobs( GncGdaBackend* be )
+{
+ static GdaQuery* query = NULL;
+ GdaObject* ret;
+ QofBook* pBook = be->primary_book;
+
+ /* First time, create the query */
+ if( query == NULL ) {
+ query = gnc_gda_create_select_query( be, TABLE_NAME );
+ }
+
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+
+ for( r = 0; r < numRows; r++ ) {
+ (void)load_single_job( be, pModel, r );
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_job_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, TABLE_NAME, col_table );
+}
+
+/* ================================================================= */
+void
+gnc_gda_save_job( GncGdaBackend* be, QofInstance* inst )
+{
+ GncJob* job = GNC_JOB(inst);
+ const GUID* guid;
+
+ (void)gnc_gda_do_db_operation( be,
+ (qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+ TABLE_NAME,
+ GNC_ID_JOB, job,
+ col_table );
+
+ // Now, commit or delete any slots
+ guid = qof_instance_get_guid( inst );
+ if( !qof_instance_get_destroying(inst) ) {
+ gnc_gda_slots_save( be, guid, qof_instance_get_slots( inst ) );
+ } else {
+ gnc_gda_slots_delete( be, guid );
+ }
+}
+
+/* ================================================================= */
+void
+gnc_job_gda_initialize( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_JOB,
+ gnc_gda_save_job, /* commit */
+ load_all_jobs, /* initial_load */
+ create_job_tables /* create_tables */
+ };
+
+ qof_object_register_backend( GNC_ID_JOB, GNC_GDA_BACKEND, &be_data );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-job-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-job-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-job-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,35 @@
+/*
+ * gnc-job-gda.h -- job gda backend
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ */
+
+/** @file gnc-job-gda.h
+ * @brief load and save job data to SQL via libgda
+ * @author Copyright (c) 2007 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_JOB_GDA_H
+#define GNC_JOB_GDA_H
+
+void gnc_job_gda_initialize( void );
+
+#endif /* GNC_JOB_GDA_H */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-order-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-order-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-order-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,192 @@
+/********************************************************************\
+ * gnc-order-gda.c -- order gda backend *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+#include "config.h"
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libgda/libgda.h>
+
+#include "gnc-backend-util-gda.h"
+
+#include "gncOrderP.h"
+
+#include "gnc-order-gda.h"
+#include "gnc-owner-gda.h"
+
+#define _GNC_MOD_NAME GNC_ID_ORDER
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define TABLE_NAME "orders"
+
+#define MAX_ID_LEN 50
+#define MAX_NOTES_LEN 50
+#define MAX_REFERENCE_LEN 50
+
+static col_cvt_t col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "id", CT_STRING, MAX_ID_LEN, COL_NNUL, NULL, ORDER_ID },
+ { "notes", CT_STRING, MAX_NOTES_LEN, COL_NNUL, NULL, ORDER_NOTES },
+ { "reference", CT_STRING, MAX_REFERENCE_LEN, COL_NNUL, NULL, ORDER_REFERENCE },
+ { "active", CT_BOOLEAN, 0, COL_NNUL, NULL, QOF_PARAM_ACTIVE },
+ { "date_opened", CT_TIMESPEC, 0, COL_NNUL, NULL, ORDER_OPENED },
+ { "date_closed", CT_TIMESPEC, 0, COL_NNUL, NULL, ORDER_CLOSED },
+ { NULL },
+};
+
+#if 0
+/* ids */
+#define order_owner_string "order:owner"
+
+ xmlAddChild(ret, gnc_owner_to_dom_tree (order_owner_string,
+ gncOrderGetOwner (order)));
+#endif
+
+static GncOrder*
+load_single_order( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ const GUID* guid;
+ GUID v_guid;
+ GncOrder* pOrder;
+
+ guid = gnc_gda_load_guid( be, pModel, row );
+ v_guid = *guid;
+
+ pOrder = gncOrderLookup( be->primary_book, &v_guid );
+ if( pOrder == NULL ) {
+ pOrder = gncOrderCreate( be->primary_book );
+ }
+ gnc_gda_load_object( be, pModel, row, GNC_ID_ORDER, pOrder, col_table );
+ gnc_gda_slots_load( be, qof_instance_get_guid( QOF_INSTANCE( pOrder )),
+ qof_instance_get_slots( QOF_INSTANCE(pOrder) ) );
+
+ qof_instance_mark_clean( QOF_INSTANCE(pOrder) );
+
+ return pOrder;
+}
+
+static void
+load_all_orders( GncGdaBackend* be )
+{
+ static GdaQuery* query = NULL;
+ GdaObject* ret;
+ QofBook* pBook = be->primary_book;
+
+ /* First time, create the query */
+ if( query == NULL ) {
+ query = gnc_gda_create_select_query( be, TABLE_NAME );
+ }
+
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+
+ for( r = 0; r < numRows; r++ ) {
+ (void)load_single_order( be, pModel, r );
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_order_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, TABLE_NAME, col_table );
+}
+
+/* ================================================================= */
+void
+gnc_gda_save_order( GncGdaBackend* be, QofInstance* inst )
+{
+ GncOrder* v = GNC_ORDER(inst);
+ const GUID* guid;
+
+ (void)gnc_gda_do_db_operation( be,
+ (qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+ TABLE_NAME,
+ GNC_ID_ORDER, v,
+ col_table );
+
+ // Now, commit or delete any slots
+ guid = qof_instance_get_guid( inst );
+ if( !qof_instance_get_destroying(inst) ) {
+ gnc_gda_slots_save( be, guid, qof_instance_get_slots( inst ) );
+ } else {
+ gnc_gda_slots_delete( be, guid );
+ }
+}
+
+/* ================================================================= */
+static void
+load_order_guid( const GncGdaBackend* be, GdaDataModel* pModel, gint row,
+ QofSetterFunc setter, gpointer pObject,
+ const col_cvt_t* table )
+{
+ const GValue* val;
+ GUID guid;
+ const GUID* pGuid;
+ GncOrder* order = NULL;
+
+ 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;
+ }
+ if( pGuid != NULL ) {
+ order = gncOrderLookup( be->primary_book, pGuid );
+ }
+ if( table->gobj_param_name != NULL ) {
+ g_object_set( pObject, table->gobj_param_name, order, NULL );
+ } else {
+ (*setter)( pObject, (const gpointer)order );
+ }
+}
+
+static col_type_handler_t order_guid_handler =
+ { load_order_guid, gnc_gda_create_objectref_guid_col,
+ gnc_gda_get_gvalue_objectref_guid_for_query, gnc_gda_get_gvalue_objectref_guid_cond };
+/* ================================================================= */
+void
+gnc_order_gda_initialize( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_ORDER,
+ gnc_gda_save_order, /* commit */
+ load_all_orders, /* initial_load */
+ create_order_tables /* create_tables */
+ };
+
+ qof_object_register_backend( GNC_ID_ORDER, GNC_GDA_BACKEND, &be_data );
+
+ gnc_gda_register_col_type_handler( CT_ORDERREF, &order_guid_handler );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-order-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-order-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-order-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,37 @@
+/*
+ * gnc-order-gda.h -- order gda backend
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ */
+
+/** @file gnc-order-gda.h
+ * @brief load and save order data to SQL via libgda
+ * @author Copyright (c) 2007 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_ORDER_GDA_H
+#define GNC_ORDER_GDA_H
+
+#define CT_ORDERREF "order"
+
+void gnc_order_gda_initialize( void );
+
+#endif /* GNC_ORDER_GDA_H */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-vendor-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-vendor-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-vendor-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,185 @@
+/********************************************************************\
+ * gnc-vendor-gda.c -- vendor gda backend *
+ * *
+ * Copyright (C) 2002 Derek Atkins <warlord at MIT.EDU> *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+#include "config.h"
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libgda/libgda.h>
+
+#include "gnc-backend-util-gda.h"
+
+#include "gnc-commodity.h"
+#include "gncBillTermP.h"
+#include "gncVendorP.h"
+#include "gncTaxTableP.h"
+#include "gnc-vendor-gda.h"
+#include "gnc-address-gda.h"
+#include "gnc-bill-term-gda.h"
+
+#define _GNC_MOD_NAME GNC_ID_VENDOR
+
+static QofLogModule log_module = GNC_MOD_BACKEND;
+
+#define MAX_NAME_LEN 50
+#define MAX_ID_LEN 50
+#define MAX_NOTES_LEN 100
+
+#define TABLE_NAME "vendors"
+
+static col_cvt_t col_table[] =
+{
+ { "guid", CT_GUID, 0, COL_NNUL, "guid" },
+ { "name", CT_STRING, MAX_NAME_LEN, COL_NNUL, NULL, VENDOR_NAME },
+ { "id", CT_STRING, MAX_ID_LEN, COL_NNUL, NULL, VENDOR_ID },
+ { "notes", CT_STRING, MAX_NOTES_LEN, COL_NNUL, NULL, VENDOR_NOTES },
+ { "currency", CT_COMMODITYREF, 0, COL_NNUL, NULL, NULL,
+ (QofAccessFunc)gncVendorGetCurrency, (QofSetterFunc)gncVendorSetCurrency },
+ { "active", CT_BOOLEAN, 0, COL_NNUL, NULL, NULL,
+ (QofAccessFunc)gncVendorGetActive, (QofSetterFunc)gncVendorSetActive },
+ { "tax_override", CT_BOOLEAN, 0, COL_NNUL, NULL, VENDOR_TAX_OVERRIDE },
+ { "addr", CT_ADDRESS, 0, 0, NULL, VENDOR_ADDR },
+ { NULL }
+};
+
+#if 0
+#define vendor_terms_string "vendor:terms"
+#define vendor_taxtable_string "vendor:taxtable"
+#define vendor_taxtableoverride_string "vendor:use-tt"
+
+ term = gncVendorGetTerms (vendor);
+ if (term)
+ xmlAddChild(ret, guid_to_dom_tree(vendor_terms_string,
+ qof_instance_get_guid(QOF_INSTANCE(term))));
+
+ xmlAddChild(ret, text_to_dom_tree(vendor_taxincluded_string,
+ gncTaxIncludedTypeToString (
+ gncVendorGetTaxIncluded (vendor))));
+
+ taxtable = gncVendorGetTaxTable (vendor);
+ if (taxtable)
+ xmlAddChild (ret, guid_to_dom_tree (vendor_taxtable_string,
+ qof_instance_get_guid(QOF_INSTANCE(taxtable))));
+
+ return ret;
+}
+#endif
+
+static GncVendor*
+load_single_vendor( GncGdaBackend* be, GdaDataModel* pModel, int row )
+{
+ const GUID* guid;
+ GUID v_guid;
+ GncVendor* pVendor;
+
+ guid = gnc_gda_load_guid( be, pModel, row );
+ v_guid = *guid;
+
+ pVendor = gncVendorLookup( be->primary_book, &v_guid );
+ if( pVendor == NULL ) {
+ pVendor = gncVendorCreate( be->primary_book );
+ }
+ gnc_gda_load_object( be, pModel, row, GNC_ID_VENDOR, pVendor, col_table );
+ gnc_gda_slots_load( be, qof_instance_get_guid( QOF_INSTANCE( pVendor )),
+ qof_instance_get_slots( QOF_INSTANCE(pVendor) ) );
+
+ qof_instance_mark_clean( QOF_INSTANCE(pVendor) );
+
+ return pVendor;
+}
+
+static void
+load_all_vendors( GncGdaBackend* be )
+{
+ static GdaQuery* query = NULL;
+ GdaObject* ret;
+ QofBook* pBook = be->primary_book;
+
+ /* First time, create the query */
+ if( query == NULL ) {
+ query = gnc_gda_create_select_query( be, TABLE_NAME );
+ }
+
+ ret = gnc_gda_execute_query( be, query );
+ if( GDA_IS_DATA_MODEL( ret ) ) {
+ GdaDataModel* pModel = GDA_DATA_MODEL(ret);
+ int numRows = gda_data_model_get_n_rows( pModel );
+ int r;
+
+ for( r = 0; r < numRows; r++ ) {
+ (void)load_single_vendor( be, pModel, r );
+ }
+ }
+}
+
+/* ================================================================= */
+static void
+create_vendor_tables( GncGdaBackend* be )
+{
+ gnc_gda_create_table_if_needed( be, TABLE_NAME, col_table );
+}
+
+/* ================================================================= */
+void
+gnc_gda_save_vendor( GncGdaBackend* be, QofInstance* inst )
+{
+ GncVendor* v = GNC_VENDOR(inst);
+ const GUID* guid;
+
+ // Ensure the commodity is in the db
+ gnc_gda_save_commodity( be, gncVendorGetCurrency( v ) );
+
+ (void)gnc_gda_do_db_operation( be,
+ (qof_instance_get_destroying(inst) ? OP_DB_DELETE : OP_DB_ADD_OR_UPDATE ),
+ TABLE_NAME,
+ GNC_ID_VENDOR, v,
+ col_table );
+
+ // Now, commit or delete any slots
+ guid = qof_instance_get_guid( inst );
+ if( !qof_instance_get_destroying(inst) ) {
+ gnc_gda_slots_save( be, guid, qof_instance_get_slots( inst ) );
+ } else {
+ gnc_gda_slots_delete( be, guid );
+ }
+}
+
+/* ================================================================= */
+void
+gnc_vendor_gda_initialize( void )
+{
+ static GncGdaDataType_t be_data =
+ {
+ GNC_GDA_BACKEND_VERSION,
+ GNC_ID_VENDOR,
+ gnc_gda_save_vendor, /* commit */
+ load_all_vendors, /* initial_load */
+ create_vendor_tables /* create_tables */
+ };
+
+ qof_object_register_backend( GNC_ID_VENDOR, GNC_GDA_BACKEND, &be_data );
+}
+/* ========================== END OF FILE ===================== */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-vendor-gda.h
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-vendor-gda.h (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gnc-vendor-gda.h 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,35 @@
+/*
+ * gnc-vendor-gda.h -- vendor gda backend
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ */
+
+/** @file gnc-vendor-gda.h
+ * @brief load and save vendor data to SQL via libgda
+ * @author Copyright (c) 2007 Phil Longstaff <plongstaff at rogers.com>
+ *
+ * This file implements the top-level QofBackend API for saving/
+ * restoring data to/from an SQL database via libgda
+ */
+
+#ifndef GNC_VENDOR_GDA_H
+#define GNC_VENDOR_GDA_H
+
+void gnc_vendor_gda_initialize( void );
+
+#endif /* GNC_VENDOR_GDA_H */
Added: gnucash/branches/gda-dev2/src/business/business-core/gda/gncmod-business-backend-gda.c
===================================================================
--- gnucash/branches/gda-dev2/src/business/business-core/gda/gncmod-business-backend-gda.c (rev 0)
+++ gnucash/branches/gda-dev2/src/business/business-core/gda/gncmod-business-backend-gda.c 2007-12-23 20:25:56 UTC (rev 16700)
@@ -0,0 +1,110 @@
+/*********************************************************************
+ * gncmod-business-backend-gda.c
+ * module definition/initialization for the gda backend module
+ *
+ * Copyright (c) 2002 Derek Atkins <warlord at MIT.EDU>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ *
+ *********************************************************************/
+
+#include "config.h"
+#include <gmodule.h>
+
+#include "gnc-module.h"
+#include "gnc-module-api.h"
+#include "gnc-engine.h"
+
+#include "gnc-address-gda.h"
+#include "gnc-bill-term-gda.h"
+#include "gnc-customer-gda.h"
+#include "gnc-employee-gda.h"
+#include "gnc-entry-gda.h"
+#include "gnc-invoice-gda.h"
+#include "gnc-job-gda.h"
+#include "gnc-order-gda.h"
+#include "gnc-owner-gda.h"
+#include "gnc-tax-table-gda.h"
+#include "gnc-vendor-gda.h"
+
+GNC_MODULE_API_DECL(libgncmod_business_backend_gda)
+
+/* version of the gnc module system interface we require */
+int libgncmod_business_backend_gda_gnc_module_system_interface = 0;
+
+/* module versioning uses libtool semantics. */
+int libgncmod_business_backend_gda_gnc_module_current = 0;
+int libgncmod_business_backend_gda_gnc_module_revision = 0;
+int libgncmod_business_backend_gda_gnc_module_age = 0;
+
+static GNCModule bus_core;
+
+
+gchar *
+libgncmod_business_backend_gda_gnc_module_path(void)
+{
+ return g_strdup( "gnucash/business-core-gda" );
+}
+
+gchar *
+libgncmod_business_backend_gda_gnc_module_description(void)
+{
+ return g_strdup( "The GDA backend for GnuCash business objects" );
+}
+
+int
+libgncmod_business_backend_gda_gnc_module_init(int refcount)
+{
+ if(!gnc_engine_is_initialized()) { return FALSE; }
+
+ bus_core = gnc_module_load( "gnucash/business-core", 0 );
+ if( !bus_core ) return FALSE;
+
+ if( refcount == 0 ) {
+ /* Initialize our pointers into the backend subsystem */
+ gnc_address_gda_initialize();
+ gnc_billterm_gda_initialize();
+ gnc_customer_gda_initialize();
+ gnc_employee_gda_initialize();
+// gnc_entry_gda_initialize();
+ gnc_invoice_gda_initialize();
+ gnc_job_gda_initialize();
+ gnc_order_gda_initialize();
+// gnc_owner_gda_initialize();
+// gnc_taxtable_gda_initialize();
+ gnc_vendor_gda_initialize();
+ }
+
+ return TRUE;
+}
+
+int
+libgncmod_business_backend_gda_gnc_module_end(int refcount)
+{
+ int unload = TRUE;
+
+ if( bus_core ) {
+ unload = gnc_module_unload( bus_core );
+ }
+
+ if( refcount == 0 ) {
+ bus_core = NULL;
+ }
+
+ return unload;
+}
Copied: gnucash/branches/gda-dev2/src/business/business-core/xml (from rev 16699, gnucash/branches/gda-dev2/src/business/business-core/file)
More information about the gnucash-changes
mailing list