book.c

00001 /********************************************************************\
00002  * book.c -- implements book handling for postgres backend          *
00003  * Copyright (c) 2000, 2001, 2002 Linas Vepstas <linas@linas.org>   *
00004  *                                                                  *
00005  * This program is free software; you can redistribute it and/or    *
00006  * modify it under the terms of the GNU General Public License as   *
00007  * published by the Free Software Foundation; either version 2 of   *
00008  * the License, or (at your option) any later version.              *
00009  *                                                                  *
00010  * This program is distributed in the hope that it will be useful,  *
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00013  * GNU General Public License for more details.                     *
00014  *                                                                  *
00015  * You should have received a copy of the GNU General Public License*
00016  * along with this program; if not, contact:                        *
00017  *                                                                  *
00018  * Free Software Foundation           Voice:  +1-617-542-5942       *
00019  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00020  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00021 \********************************************************************/
00022 
00023 #include "config.h"
00024 
00025 #include <glib.h>
00026 #include <stdlib.h>  
00027 #include <string.h>  
00028 
00029 #include <libpq-fe.h>  
00030  
00031 #include "qof.h"
00032 #include "book.h"
00033 #include "gnc-pricedb.h"
00034 #include "kvp-sql.h"
00035 #include "PostgresBackend.h"
00036 
00037 #include "gnc-engine.h"
00038 #include "base-autogen.h"
00039 
00040 #include "putil.h"
00041 
00042 static QofLogModule log_module = GNC_MOD_BACKEND; 
00043 
00044 /* ============================================================= */
00045 /* ============================================================= */
00046 /*                        BOOK STUFF                             */
00047 /*      (UTILITIES FIRST, THEN SETTERS, THEN GETTERS)            */
00048 /* ============================================================= */
00049 /* ============================================================= */
00050 
00051 /* ============================================================= */
00052 /* The pgendStoreBook() routine stores everything in the book 
00053  * to the database.  That is, the engine data is written out to the 
00054  * database.  
00055  *
00056  * If do_mark is set to TRUE, then this routine sets a mark
00057  * to terminate recursion.  That is,  it will only store the
00058  * account once; a second call on a marked account will simply 
00059  * return.  Be sure to clear the mark when done!
00060  *
00061  * If the do_check_version flag is set, then this routine
00062  * will compare the engine and sql db version numbrs, and
00063  * perform the store only if the engine version is equal 
00064  * or newer than the sql version.
00065  *
00066  */
00067 
00068 void
00069 pgendStoreBookNoLock (PGBackend *be, QofBook *book,
00070                          gboolean do_check_version)
00071 {
00072    guint32 idata;
00073    if (!be || !book) return;
00074 
00075    ENTER ("book=%p", book);
00076 
00077    if (do_check_version)
00078    {
00079      if (0 < pgendBookCompareVersion (be, book)) return;
00080    }
00081    qof_book_set_version(book, (qof_book_get_version(book) +1));  /* be sure to update the version !! */
00082 
00083    if ((0 == qof_instance_get_idata(book)) &&
00084        (FALSE == kvp_frame_is_empty (qof_book_get_slots(book))))
00085    {
00086       qof_instance_set_idata(book, pgendNewGUIDidx(be));
00087    }
00088 
00089    pgendPutOneBookOnly (be, book);
00090    idata = qof_instance_get_idata(book);
00091    if ( idata > 0)
00092    {
00093       pgendKVPDelete (be, idata);
00094       pgendKVPStore (be, idata, qof_instance_get_slots((QofInstance*)book));
00095    }
00096    LEAVE(" ");
00097 }
00098 
00099 void
00100 pgendStoreBook (PGBackend *be, QofBook *book)
00101 {
00102    char *p;
00103    ENTER ("be=%p, book=%p", be, book);
00104    if (!be || !book) return;
00105 
00106    /* lock it up so that we store atomically */
00107    p = "BEGIN;\n"
00108        "LOCK TABLE gncBook IN EXCLUSIVE MODE;\n";
00109    SEND_QUERY (be,p, );
00110    FINISH_QUERY(be->connection);
00111 
00112    pgendStoreBookNoLock (be, book, TRUE);
00113 
00114    p = "COMMIT;\n"
00115        "NOTIFY gncBook;";
00116    SEND_QUERY (be,p, );
00117    FINISH_QUERY(be->connection);
00118    LEAVE(" ");
00119 }
00120 
00121 
00122 /* ============================================================= */
00123 /*           BOOK GETTERS (SETTERS ARE ABOVE)                    */
00124 /* ============================================================= */
00125 
00126 /* ============================================================= */
00127 /* The pgendBookRestore() routine restores the all book data,
00128  * including the account heirarchy, the price db, commodities, etc.
00129  */
00130 
00131 static gpointer
00132 get_one_book_cb (PGBackend *be, PGresult *result, int j, gpointer data)
00133 {
00134    QofBook *book = (QofBook *) data;
00135    GUID guid;
00136 
00137    /* first, lets see if we've already got this one */
00138    PINFO ("book GUID=%s", DB_GET_VAL("bookGuid",j));
00139    guid = nullguid;  /* just in case the read fails ... */
00140    string_to_guid (DB_GET_VAL("bookGuid",j), &guid);
00141 
00142    qof_instance_set_guid (QOF_INSTANCE(book), &guid);
00143 
00144    if((DB_GET_VAL("book_open",j))[0] == 'n')
00145    {
00146                 qof_book_mark_closed(book);
00147    }
00148    qof_book_set_version(book, atoi(DB_GET_VAL("version",j)));
00149    qof_instance_set_idata(book, atoi(DB_GET_VAL("iguid",j)));
00150 
00151    return book;
00152 }
00153 
00154 static void pg_kvp_helper (const char* key, KvpValue *value, gpointer data)
00155 {
00156         QofBook *book = (QofBook*)data;
00157         kvp_frame_set_slot_nc(qof_instance_get_slots((QofInstance*)book),
00158                 key, value);
00159 }
00160 
00161 void
00162 pgendBookRestore (PGBackend *be, QofBook *book)
00163 {
00164    char * bufp;
00165 
00166    ENTER ("be=%p", be);
00167    if (!be) return;
00168 
00169    /* For right now, get only the currently open book 
00170     * In theory, we should pass a guid into this routine, 
00171     * and fetch books based on that. 
00172     */
00173    bufp = "SELECT * FROM gncBook WHERE book_open='y';";
00174    SEND_QUERY (be, bufp, );
00175    pgendGetResults (be, get_one_book_cb, book);
00176 
00177    if (0 != qof_instance_get_idata(book)) 
00178    {
00179           KvpFrame *pg_frame;
00180           
00181           pg_frame = pgendKVPFetch (be, qof_instance_get_idata(book), 
00182                 qof_instance_get_slots((QofInstance*)book));
00183           kvp_frame_for_each_slot(pg_frame, pg_kvp_helper, book);          
00184    }
00185 
00186    LEAVE (" ");
00187 }
00188 
00189 /* ============================================================= */
00190 /* The pgendGetAllBooks() routine creates an empty book
00191  * for each book in the database.
00192  */
00193 
00194 static gpointer
00195 get_book_cb (PGBackend *be, PGresult *result, int j, gpointer data)
00196 {
00197    QofBookList *blist = (QofBookList *) data;
00198    QofBookList *node;
00199    QofBook *book;
00200    GUID guid;
00201 
00202    PINFO ("book GUID=%s", DB_GET_VAL("bookGUID",j));
00203    guid = nullguid;  /* just in case the read fails ... */
00204    string_to_guid (DB_GET_VAL("bookGUID",j), &guid);
00205 
00206    /* first, lets see if we've already got this one */
00207    book = NULL;
00208    for (node=blist; node; node=node->next)
00209    {
00210       book = node->data;
00211       if (guid_equal (qof_entity_get_guid(QOF_INSTANCE(book)), &guid)) break;
00212       book = NULL;
00213    }
00214    
00215    if (!book) 
00216    {
00217       book = qof_book_new();
00218       qof_instance_set_guid (QOF_INSTANCE(book), &guid);
00219    }
00220 
00221    if((DB_GET_VAL("book_open",j))[0] == 'n')
00222    {
00223            qof_book_mark_closed(book);
00224    }
00225 //   book->book_open = (DB_GET_VAL("book_open",j))[0];
00226    qof_book_set_version(book, atoi(DB_GET_VAL("version",j)));
00227    qof_instance_set_idata(book, atoi(DB_GET_VAL("iguid",j)));
00228 
00229    return blist;
00230 }
00231 
00232 QofBookList *
00233 pgendGetAllBooks (PGBackend *be, QofBookList *blist)
00234 {
00235    QofBookList *node;
00236    char * bufp;
00237 
00238    ENTER ("be=%p", be);
00239    if (!be) return NULL;
00240 
00241    /* Get them ALL */
00242    bufp = "SELECT * FROM gncBook;";
00243    SEND_QUERY (be, bufp, NULL);
00244    blist = pgendGetResults (be, get_book_cb, blist);
00245 
00246    /* get the KVP data for each book too */
00247    for (node=blist; node; node=node->next)
00248    {
00249       QofBook *book = node->data;
00250       if (0 != qof_instance_get_idata(book)) 
00251       {
00252                 KvpFrame *pg_frame;
00253           
00254                   pg_frame = pgendKVPFetch (be, qof_instance_get_idata(book), 
00255                         qof_instance_get_slots((QofInstance*)book));
00256                   kvp_frame_for_each_slot(pg_frame, pg_kvp_helper, book);          
00257       }
00258 /*      if (0 != qof_instance_get_idata(book)) 
00259       {
00260          book->inst.kvp_data = pgendKVPFetch(be, qof_instance_get_idata(book),
00261                                              book->inst.kvp_data);
00262       }*/
00263    }
00264 
00265    LEAVE (" ");
00266    return blist;
00267 }
00268 
00269 /* ============================================================= */
00270 
00271 void 
00272 pgend_book_transfer_begin(QofBackend *bend, QofBook *newbook)
00273 {
00274    PGBackend *be = (PGBackend *) bend;
00275 
00276    ENTER (" ");
00277 
00278    /* first, store the new book */
00279    pgendStoreBook (be, newbook);
00280 
00281    LEAVE (" ");
00282 }
00283 
00284 void 
00285 pgend_book_transfer_commit(QofBackend *bend, QofBook *newbook)
00286 {
00287    /* PGBackend *be = (PGBackend *) bend; */
00288    ENTER (" ");
00289 
00290    LEAVE (" ");
00291 }
00292 
00293 /* ======================== END OF FILE ======================== */

Generated on Tue Oct 14 05:04:24 2008 for GnuCash by  doxygen 1.5.2