GnuCash Daily Diff

Dave Peticolas peticolas@linas.org
Fri, 1 Jun 2001 08:03:47 -0500 (CDT)


Index: gnucash/ChangeLog
diff -u gnucash/ChangeLog:1.535 gnucash/ChangeLog:1.542
--- gnucash/ChangeLog:1.535	Thu May 31 03:36:50 2001
+++ gnucash/ChangeLog	Fri Jun  1 03:48:38 2001
@@ -1,3 +1,42 @@
+2001-06-01  Dave Peticolas  <dave@krondo.com>
+
+	* README: update info
+
+2001-06-01  Robert Graham Merkel  <rgmerk@mira.net>
+
+	* src/scm/commodity-utilities.scm: exchange functions 
+	now return unchanged quantity if the two currencies are
+	identical.
+
+2001-06-01  Dave Peticolas  <dave@krondo.com>
+
+	* src/doc/design/engine.texinfo: document commodity table API
+
+	* src/doc/design/gnucash-design.texinfo: update docs
+
+2001-05-31  Dave Peticolas  <dave@krondo.com>
+
+	* src/engine/sixtp-dom-parsers.c (string_to_binary): fix sanity
+	checks
+	(dom_tree_to_gnc_numeric): fix mem leak
+
+	* src/test/test-dom-converters1.c (test_dom_tree_to_gnc_numeric):
+	fix bug
+
+	* src/engine/sixtp-utils.c (string_to_gint32): use intermediate
+	variable in case int != gint32.
+
+	* src/test/test-dom-converters1.c: fix spelling
+
+	* src/engine/sixtp-dom-generators.c (int_to_dom_tree): cast
+	gint64 to long long int for %lld.
+
+2001-05-31  James LewisMoss  <jimdres@mindspring.com>
+
+	* src/scm/tip-of-the-day.scm ((gnc:current-tip-number)): reset
+	number if greater.  tips read before config file so this number
+	gets reset by config file too high.
+
 2001-05-31  Dave Peticolas  <dave@krondo.com>
 
 	* src/doc/design/gnucash-design.texinfo: update docs
Index: gnucash/README
diff -u gnucash/README:1.162 gnucash/README:1.163
--- gnucash/README:1.162	Sat May 19 01:50:33 2001
+++ gnucash/README	Fri Jun  1 03:48:39 2001
@@ -1,5 +1,5 @@
 ############################################################
-          Gnucash 1.5.x README file.
+          GnuCash 1.5.x README file.
 
 NOTE: THIS IS A DEVELOPMENT RELEASE!!! THIS VERSION HAS NOT
 BEEN TESTED PROPERLY AND MAY DO ABSOLUTELY ANYTHING!  
@@ -125,10 +125,12 @@
 Dependencies
 ------------
 
-The following packages are required to be installed to run gnucash:
+The following packages are required to be installed to run GnuCash:
 
+  Gnome 1.4: see www.gnome.org for more information.
+
   guile: provides main extension language infrastructure, used
-    extensively in gnucash for initialization & startup. Requires
+    extensively in GnuCash for initialization & startup. Requires
     version 1.3.4 or later.
 
   slib: scheme libraries for guile. Need version slib2c4 or later.
@@ -144,7 +146,8 @@
   gnome-libs: version 1.0.40 or higher should work. These libraries
     require numerous other supporting libraries, such as gtk and glib.
 
-  gnome-print: any recent version should work.
+  gnome-print: any recent version should work, however problems have
+    been reported with 0.28.
 
   gdk-pixbuf: any recent version should work.
 
@@ -152,37 +155,25 @@
     version of gtkhtml from Helix Code.  Note that this has changed since
     1.4, which used the older gtkxmhtml library.
 
-  guppi: version 0.35.1-1 should work
+  guppi: version 0.35.3 should work
 
 To be able to use certain features of GnuCash, such as reports and
 network stock price downloads, you must have the following packages
 below installed (in addition to those listed above).
 
-RPM's for most of these can be found at http://rufus.w3.org/linux/
-
   perl: Almost any version of perl5 should work.  I run perl-5.004 
 
-In addition, some perl modules need to be installed:
+In addition, some perl modules need to be installed. You can run
+the script 'update-finance-quote' as root to obtain the latest
+versions of required packages.
 
-  perl-LWP/libwww-perl-5.36
-  perl-HTML/HTML-0.6
-  perl-HTML/HTML-Parser-2.20
-        -- these perl modules are used to fetch stock & mutual fund quotes
-           off the net.  You can pick up RPMS at
-           ftp://ftp.gnucash.org/pub/gnucash/binaries/RPMS
-           http://rufus.w3.org/linux/RPM/PByName.html
-           http://linas.org/linux/gnucash (last resort)
-           or sources at
-           http://www.cpan.org/CPAN.html
 
-
 #######
 Running
 -------
 
 For GnuCash invocation details, see the manpage in doc/gnucash.1.
-Soon, you'll be able to also run gnucash --help, but that's not
-finished yet...
+You can also run gnucash --help for the command line options.
 
 You can start GnuCash at the command-line, with "gnucash" or "gnucash
 <filename>", where <filename> is a GnuCash account file.  Sample
@@ -219,7 +210,7 @@
   debugging earlier in the startup process than you can with --debug.
 
 As an example, here's a wrapper script we used to use to allow you
-to run gnucash from a local directory:
+to run GnuCash from a local directory:
 
   #! /bin/sh
 
@@ -311,7 +302,7 @@
 
   --enable-opt-style-install
 
-    Gnucash supports two types of install, the first is the normal
+    GnuCash supports two types of install, the first is the normal
     /usr or /usr/local/ style, where the files are installed into
     /usr/bin /usr/lib, etc.  This is the default.
 
@@ -391,14 +382,14 @@
 or  http://linas.org/linux/gnucash (slow-www ) 
 for precompiled (but *very old*) binaries for these platforms
 
-Gnucash can probably be made to work with most POSIX-ish platforms, 
+GnuCash can probably be made to work with most POSIX-ish platforms, 
 provided the libraries and toolchain are available.
 
 #########################
 Additional Download Sites
 -------------------------
 
-You can also download gnucash from:
+You can also download GnuCash from:
 
   - http://download.sourceforge.net/gnucash
   - ftp://ftp.krondo.com
@@ -464,10 +455,10 @@
 2. Several of the directories under src contain files called design.txt
    which explain many aspects of GnuCash's design. Read those.
 
-3. Go to the gnucash website and skim the archives of the gnucash
+3. Go to the GnuCash website and skim the archives of the GnuCash
    development mailing list.
 
-4. Join the GnuCash development mailing list. See the gnucash website
+4. Join the GnuCash development mailing list. See the GnuCash website
    for details on how to do this.
 
 
@@ -476,8 +467,7 @@
   This section has been removed to the file README.patches
 
   Please consult that file for details on using the script provided to make
-  patches suitable for submitting to the gnucash development team.
+  patches suitable for submitting to the GnuCash development team.
 
 
 Thank you. 
-
Index: gnucash/src/doc/design/engine.texinfo
diff -u gnucash/src/doc/design/engine.texinfo:1.42 gnucash/src/doc/design/engine.texinfo:1.43
--- gnucash/src/doc/design/engine.texinfo:1.42	Thu May 31 03:36:54 2001
+++ gnucash/src/doc/design/engine.texinfo	Fri Jun  1 02:36:59 2001
@@ -26,6 +26,7 @@
 * Key-Value Pair Frames::       
 * Events::                      
 * Commodities::                 
+* Commodity Tables::            
 * Splits::                      
 * Transactions::                
 * Accounts::                    
@@ -1193,7 +1194,7 @@
 @end deftypefun
 
 
-@node Commodities, Splits, Events, Engine
+@node Commodities, Commodity Tables, Events, Engine
 @section Commodities
 @tindex gnc_commodity
 
@@ -1319,7 +1320,111 @@
 @end deftypefun
 
 
-@node Splits, Transactions, Commodities, Engine
+@node Commodity Tables, Splits, Commodities, Engine
+@section Commodity Tables
+@tindex gnc_commodity_table
+
+A Commodity Table holds a set of commodities and allows user code
+to add, remove, and access the commodities in the table.
+
+There is a single, global Commodity Table used by the Engine.
+
+@menu
+* General Commodity Table API::  
+* Commodity Table Access API::  
+* Commodity Table Modification API::  
+@end menu
+
+
+@node General Commodity Table API, Commodity Table Access API, Commodity Tables, Commodity Tables
+@subsection General Commodity Table API
+
+@deftypefun {gnc_commodity_table *} gnc_commodity_table_new (void)
+Allocate and initialize a @code{gnc_commodity_table}. The returned
+table must be destroyed with @code{gnc_commodity_table_destroy}.
+@end deftypefun
+
+@deftypefun void gnc_commodity_table_destroy (gnc_commodity_table * @var{table})
+Destroy @var{table} and all associated resources, including all
+Commodity objects in the table.
+@end deftypefun
+
+@deftypefun {gnc_commodity_table *} gnc_engine_commodities (void)
+Return the global engine commodity table.
+@end deftypefun
+
+
+@node Commodity Table Access API, Commodity Table Modification API, General Commodity Table API, Commodity Tables
+@subsection Commodity Table Access API
+
+@deftypefun {gnc_commodity *} gnc_commodity_table_lookup (const gnc_commodity_table * @var{table}, const char * @var{namespace}, const char * @var{mnemonic})
+Look up a commodity in @var{table} given the namespace and the mnemonic.
+If no such commodity exists, @code{NULL} is returned.
+@end deftypefun
+
+@deftypefun {gnc_commodity *} gnc_commodity_table_find_full (const gnc_commodity_table * @var{table}, const char * @var{namespace}, const char * @var{fullnam}e)
+Look up a commodity in @var{table} given the namespace and the full name.
+If no such commodity exists, @code{NULL} is returned.
+@end deftypefun
+
+@deftypefun int gnc_commodity_table_has_namespace (const gnc_commodity_table * @var{table}, const char * @var{namespace})
+Return true if @var{table} has the namespace @var{namespace}.
+@end deftypefun
+
+@deftypefun guint gnc_commodity_table_get_size (gnc_commodity_table * @var{table})
+Return the total number of commodities stored in @var{table}.
+@end deftypefun
+
+@deftypefun guint gnc_commodity_table_get_number_of_namespaces (gnc_commodity_table * @var{table})
+Return the number of distinct namespaces in @var{table}.
+@end deftypefun
+
+@deftypefun {GList *} gnc_commodity_table_get_namespaces (const gnc_commodity_table * @var{table})
+Return a list of the distinct namespaces in @var{table}. The list should
+be freed with @code{g_list_free} but the namespaces should not be freed
+or modified.
+@end deftypefun
+
+@deftypefun {GList *} gnc_commodity_table_get_commodities (const gnc_commodity_table * @var{table}, const char * @var{namespace})
+Return a list of the commodities under @var{namespace} in @var{table}.
+The list should be freed with @code{g_list_free} but the commodities
+should not be freed.
+@end deftypefun
+
+
+@node Commodity Table Modification API,  , Commodity Table Access API, Commodity Tables
+@subsection Commodity Table Modification API
+
+@deftypefun {gnc_commodity *} gnc_commodity_table_insert (gnc_commodity_table * @var{table}, gnc_commodity * @var{comm})
+Add commodity @var{comm} to @var{table}. If @var{comm}'s namespace is
+not in @var{table}, the namespace will be added. This function has
+hand-over semantics, i.e., @var{table} assumes responsibility for
+@var{comm}.  @var{comm} may even be destroyed by this call! The function
+returns the actual commodity added as a result of the call. It may not
+be the same object as @var{comm}, but will be equivalent to @var{comm}.
+@end deftypefun
+
+@deftypefun void gnc_commodity_table_remove (gnc_commodity_table * @var{table}, gnc_commodity * @var{comm})
+Remove the given commodity from @var{table}. @var{comm} is not modified
+or destroyed.
+@end deftypefun
+
+@deftypefun void gnc_commodity_table_add_namespace (gnc_commodity_table * @var{table}, const char * @var{namespace})
+Add @var{namespace} to @var{table}.
+@end deftypefun
+
+@deftypefun void gnc_commodity_table_delete_namespace (gnc_commodity_table * @var{table}, const char * @var{namespace})
+Delete @var{namespace} from @var{table} including all associated
+commodities.
+@end deftypefun
+
+@deftypefun void gnc_commodity_table_remove_non_iso (gnc_commodity_table * @var{table})
+Remove and destroy all commodities in @var{table} which are not in the
+ISO4217 namespace.
+@end deftypefun
+
+
+@node Splits, Transactions, Commodity Tables, Engine
 @section Splits
 @tindex Split
 
Index: gnucash/src/doc/design/gnucash-design.texinfo
diff -u gnucash/src/doc/design/gnucash-design.texinfo:1.30 gnucash/src/doc/design/gnucash-design.texinfo:1.31
--- gnucash/src/doc/design/gnucash-design.texinfo:1.30	Thu May 31 03:36:56 2001
+++ gnucash/src/doc/design/gnucash-design.texinfo	Fri Jun  1 02:37:01 2001
@@ -87,6 +87,7 @@
 * Key-Value Pair Frames::       
 * Events::                      
 * Commodities::                 
+* Commodity Tables::            
 * Splits::                      
 * Transactions::                
 * Accounts::                    
@@ -130,6 +131,12 @@
 * General Commodity API::       
 * Commodity Getters::           
 * Commodity Setters::           
+
+Commodity Tables
+
+* General Commodity Table API::  
+* Commodity Table Access API::  
+* Commodity Table Modification API::  
 
 Splits
 
Index: gnucash/src/engine/Query.c
diff -u gnucash/src/engine/Query.c:1.77 gnucash/src/engine/Query.c:1.79
--- gnucash/src/engine/Query.c:1.77	Tue May 29 10:20:23 2001
+++ gnucash/src/engine/Query.c	Thu May 31 12:44:58 2001
@@ -130,11 +130,21 @@
       qt = (QueryTerm *)j->data;
       switch (qt->data.base.term_type) 
       {
-        case PR_ACCOUNT:
+        case PR_ACCOUNT: {
+          GList *p;
+          char buff[40];
           printf ("account sense=%d how=%d\n",
                   qt->data.base.sense,
                   qt->data.acct.how);
+          for (p=qt->data.acct.account_guids; p; p=p->next) {
+             guid_to_string_buff (p->data, buff);
+             printf ("\tguid=%s\n", buff);
+          }
+          for (p=qt->data.acct.accounts; p; p=p->next) {
+             printf ("\tacct ptr=%p\n", p->data);
+          }
           break;
+        }
         case PR_ACTION:
           printf ("action\n");
           break;
@@ -258,16 +268,31 @@
 
 /********************************************************************
  * xaccQueryHasTerms
- * returns the number of terms in the query, which is generally
+ * returns the number of 'OR' terms in the query, which is generally
  * used as a truth test.
  ********************************************************************/
 
 int
-xaccQueryHasTerms(Query * q) {
+xaccQueryHasTerms(Query * q) 
+{
   if (!q)
     return 0;
 
   return g_list_length(q->terms);    
+}
+
+int
+xaccQueryNumTerms(Query * q) 
+{
+  GList *o;
+  int n=0;
+  if (!q)
+    return 0;
+
+  for(o=q->terms; o; o=o->next) {
+     n += g_list_length(o->data);    
+  }
+  return n;
 }
 
 GList *
Index: gnucash/src/engine/Query.h
diff -u gnucash/src/engine/Query.h:1.45 gnucash/src/engine/Query.h:1.46
--- gnucash/src/engine/Query.h:1.45	Mon Apr 30 21:14:14 2001
+++ gnucash/src/engine/Query.h	Thu May 31 12:44:57 2001
@@ -242,10 +242,16 @@
 Query       * xaccQueryMerge(Query * q1, Query * q2, QueryOp op);
 void          xaccQueryClear(Query * q);
 
+/* The xaccQueryHasTerms() routine returns the number of 'OR' terms in the query.
+ * The xaccQueryNumTerms() routine returns the total number of terms in the query.
+ */
+
 void          xaccQueryPurgeTerms(Query * q, pd_type_t type);
 int           xaccQueryHasTerms(Query * q);
 gboolean      xaccQueryHasTermType(Query * q, pd_type_t type);
 GList       * xaccQueryGetTerms(Query * q);
+int           xaccQueryNumTerms(Query * q); 
+
 
 /* after the query has been set up, call this to run the query */
 GList       * xaccQueryGetSplits(Query * q);
Index: gnucash/src/engine/sixtp-dom-generators.c
diff -u gnucash/src/engine/sixtp-dom-generators.c:1.13 gnucash/src/engine/sixtp-dom-generators.c:1.14
--- gnucash/src/engine/sixtp-dom-generators.c:1.13	Tue May 15 10:50:05 2001
+++ gnucash/src/engine/sixtp-dom-generators.c	Thu May 31 15:00:43 2001
@@ -54,8 +54,8 @@
 {
     gchar *text;
     xmlNodePtr result;
-    
-    text = g_strdup_printf("%lld", val);
+
+    text = g_strdup_printf("%lld", (long long int) val);
     result = text_to_dom_tree(tag, text);
     g_free(text);
     return result;
Index: gnucash/src/engine/sixtp-dom-parsers.c
diff -u gnucash/src/engine/sixtp-dom-parsers.c:1.18 gnucash/src/engine/sixtp-dom-parsers.c:1.20
--- gnucash/src/engine/sixtp-dom-parsers.c:1.18	Sat May 19 05:02:35 2001
+++ gnucash/src/engine/sixtp-dom-parsers.c	Fri Jun  1 02:37:03 2001
@@ -183,7 +183,10 @@
   guint64 str_len;
   guchar *data;
   int i, j;
-  
+
+  g_return_val_if_fail(v != NULL, FALSE);
+  g_return_val_if_fail(data_len != NULL, FALSE);
+
   str_len = strlen(str);
 
   /* Since no whitespace is allowed and hex encoding is 2 text chars
@@ -193,14 +196,12 @@
       return(FALSE);
   *data_len = str_len / 2;
   data = g_new0(guchar, *data_len);
-  
-  g_return_val_if_fail(*v, FALSE);
 
   for(j = 0, i = 0; i < str_len; i += 2, j++)
   {
       gchar tmpstr[3];
       long int converted;
-      
+
       tmpstr[0] = str[i];
       tmpstr[1] = str[i + 1];
       tmpstr[2] = '\0';
@@ -211,7 +212,7 @@
   }
 
   *v = data;
-  
+
   return(TRUE);
 }
 
@@ -465,6 +466,7 @@
     }
     else
     {
+        g_free(content);
         g_free(ret);
         return NULL;
     }
Index: gnucash/src/engine/sixtp-utils.c
diff -u gnucash/src/engine/sixtp-utils.c:1.13 gnucash/src/engine/sixtp-utils.c:1.14
--- gnucash/src/engine/sixtp-utils.c:1.13	Wed May 30 03:13:49 2001
+++ gnucash/src/engine/sixtp-utils.c	Thu May 31 15:00:43 2001
@@ -214,13 +214,17 @@
 
 gboolean
 string_to_gint32(const gchar *str, gint32 *v) {
-  /* convert a string to a gint32.  only whitespace allowed before and after. */
+  /* convert a string to a gint32. only whitespace allowed before and after. */
   int num_read;
+  int v_in;
 
   /* must use "<" here because %n's effects aren't well defined */
-  if(sscanf(str, " %d %n", v, &num_read) < 1) {
+  if(sscanf(str, " %d %n", &v_in, &num_read) < 1) {
     return(FALSE);
   }
+
+  if (v)
+    *v = v_in;
 
   if(!isspace_str(str + num_read, -1)) return(FALSE);
   return(TRUE);
Index: gnucash/src/engine/sql/PostgresBackend.c
diff -u gnucash/src/engine/sql/PostgresBackend.c:1.49 gnucash/src/engine/sql/PostgresBackend.c:1.52
--- gnucash/src/engine/sql/PostgresBackend.c:1.49	Mon May 28 11:39:04 2001
+++ gnucash/src/engine/sql/PostgresBackend.c	Thu May 31 15:06:42 2001
@@ -1276,6 +1276,45 @@
 }
 
 /* ============================================================= */
+/* The RunQueryToCheckpoint() routine performs the query as above.
+ * However, it first fleshes out the query to the nearest checkpoints,
+ * so that when the user opens a register window, the starting balance
+ * has been correctly set for the display.
+ *
+ * This is very much a hack at this point, since we adjust only one 
+ * very special query.  BTW, its buggy at the moment anyway.
+ */
+
+static void 
+pgendRunQueryToCheckpoint (Backend *bend, Query *q)
+{
+   PGBackend *be = (PGBackend *)bend;
+
+   if (!be || !q) return;
+   
+   PERR ("incompletely implemented");
+   pgendRunQuery (bend, q);
+
+ xaccQueryPrint (q);
+
+   if ((1 == xaccQueryNumTerms(q)) && xaccQueryHasTermType(q, PD_ACCOUNT)) {
+      GList *o, *a, *p;
+      QueryTerm *qt;
+      Account *acct;
+      Timespec ts = gnc_iso8601_to_timespec_local (CK_AFTER_EARLIEST_DATE);
+
+      o = xaccQueryGetTerms(q); 
+      a = o->data;
+      qt = a->data;
+      for (p=qt->data.acct.accounts; p; p=p->next) {
+         pgendAccountGetBalance (be, p->data, ts.tv_sec);
+      }
+   }
+
+// xxx
+}
+
+/* ============================================================= */
 /* The pgendGetAllTransactions() routine sucks *all* of the 
  *    transactions out of the database.  This is a potential 
  *    CPU and memory-burner; its use is not suggested for anything
@@ -1781,7 +1820,8 @@
    if ((MODE_SINGLE_FILE != be->session_mode) &&
        (MODE_SINGLE_UPDATE != be->session_mode))
    {
-      pgendGroupGetAllCheckpoints (be, grp);
+      Timespec ts = gnc_iso8601_to_timespec_local (CK_AFTER_LAST_DATE);
+      pgendGroupGetAllBalances (be, grp, ts.tv_sec);
    } 
    else
    {
@@ -2194,6 +2234,7 @@
 static AccountGroup *
 pgend_book_load_poll (Backend *bend)
 {
+   Timespec ts = gnc_iso8601_to_timespec_local (CK_AFTER_LAST_DATE);
    AccountGroup *grp;
    PGBackend *be = (PGBackend *)bend;
    if (!be) return NULL;
@@ -2204,7 +2245,7 @@
 
    pgendKVPInit(be);
    grp = pgendGetAllAccounts (be, NULL);
-   pgendGroupGetAllCheckpoints (be, grp);
+   pgendGroupGetAllBalances (be, grp, ts.tv_sec);
 
    /* re-enable events */
    pgendEnable(be);
@@ -2690,7 +2731,7 @@
             be->be.trans_rollback_edit = NULL;
             be->be.price_begin_edit = pgend_price_begin_edit;
             be->be.price_commit_edit = pgend_price_commit_edit;
-            be->be.run_query = pgendRunQuery;
+            be->be.run_query = pgendRunQueryToCheckpoint;
             be->be.sync = pgendSync;
             be->be.sync_price = pgendSyncPriceDB;
             PWARN ("MODE_POLL is experimental -- you might corrupt your data\n");
Index: gnucash/src/engine/sql/PostgresBackend.h
diff -u gnucash/src/engine/sql/PostgresBackend.h:1.11 gnucash/src/engine/sql/PostgresBackend.h:1.13
--- gnucash/src/engine/sql/PostgresBackend.h:1.11	Tue May 29 00:22:58 2001
+++ gnucash/src/engine/sql/PostgresBackend.h	Thu May 31 15:06:43 2001
@@ -102,7 +102,14 @@
 /* -------------------------------------------------------- */
 /* the following prototypes belong in a 'checkpoint.h' file */
 
-void pgendGroupRecomputeAllCheckpoints (PGBackend *be, AccountGroup *grp);
-void pgendGroupGetAllCheckpoints (PGBackend *be, AccountGroup*grp);
+#define CK_EARLIEST_DATE "1903-01-02 08:35:46.00"
+#define CK_AFTER_EARLIEST_DATE "1903-01-03 03:03:03.00"
+#define CK_LAST_DATE "2038-01-02 08:35:46.00"
+#define CK_AFTER_LAST_DATE "2038-01-02 12:12:12.00"
+
+
+void pgendGroupRecomputeAllCheckpoints (PGBackend *, AccountGroup *);
+void pgendGroupGetAllBalances (PGBackend *, AccountGroup *, gint64 as_of_date);
+void pgendAccountGetBalance (PGBackend *, Account *, gint64 as_of_date);
 
 #endif /* __POSTGRES_BACKEND_H__ */
Index: gnucash/src/engine/sql/README
diff -u gnucash/src/engine/sql/README:1.32 gnucash/src/engine/sql/README:1.33
--- gnucash/src/engine/sql/README:1.32	Tue May 29 00:57:27 2001
+++ gnucash/src/engine/sql/README	Thu May 31 15:06:43 2001
@@ -219,8 +219,15 @@
 Most of the items on this list are 'critical' in the sense that
 multi-user mode is fundamentally broken unless they are fixed. 
 
--- checkpoint ending balance is showing up as starting balance
+-- checkpoint balance is broken for the type of queries used in
+   reports. 
 
+-- checkpoint balance is broken for when register asks for only a small
+   number of splits.
+
+-- provide support for more query types in gncquery.c
+   (reports are currently broken as a result).
+
 -- if another user deletes a transaction, or an account, there is no way
    for us to know.  Thus, any sort of sync will probably (incorrectly)
    add the deleted transaction back in.  Question: what is the best way
@@ -235,12 +242,6 @@
    and transactions.  See the notes for pgendSync() for details
    as to what this is about.  For the first pass, this is not a 
    serious issue; its a 'nice to have' thing.
-
--- store account balances in database.  This will be tricky ...
-   -- split query gets hard ... 
-   -- use postgres aggregates ?? 
-
--- provide support for more query types in gncquery.c
 
 -- add support for price queries.
 
Index: gnucash/src/engine/sql/checkpoint.c
diff -u gnucash/src/engine/sql/checkpoint.c:1.7 gnucash/src/engine/sql/checkpoint.c:1.9
--- gnucash/src/engine/sql/checkpoint.c:1.7	Tue May 29 00:22:58 2001
+++ gnucash/src/engine/sql/checkpoint.c	Thu May 31 15:06:43 2001
@@ -90,7 +90,7 @@
    /* malloc a new checkpoint, set it to the dawn of unix time ... */
    bp = g_chunk_new0 (Checkpoint, chunk);
    checkpoints = g_list_prepend (checkpoints, bp);
-   this_ts = gnc_iso8601_to_timespec_local ("1903-01-02 08:35:46.00");
+   this_ts = gnc_iso8601_to_timespec_local (CK_EARLIEST_DATE);
    bp->date_start = this_ts;
    bp->account_guid = acct_guid;
    bp->commodity = commodity_name;
@@ -167,7 +167,7 @@
 done:
 
    /* set the timestamp on the final checkpoint into the distant future */
-   this_ts = gnc_iso8601_to_timespec_local ("2038-01-02 08:35:46.00");
+   this_ts = gnc_iso8601_to_timespec_local (CK_LAST_DATE);
    bp->date_end = this_ts;
 
    /* now store the checkpoints */
@@ -231,18 +231,19 @@
    if (!be || !chk) return;
    ENTER("be=%p", be);
 
-/* XXX this is totally wrong */
    /* create the query we need */
    p = be->buff; *p = 0;
-   p = stpcpy (p, "SELECT balance, cleared_balance, reconciled_balance "
-                  "FROM gncCheckpoint "
-                  "WHERE accountGuid='");
+   p = stpcpy (p, "SELECT sum(balance) AS baln, "
+                  "       sum(cleared_balance) AS cleared_baln, "
+                  "       sum(reconciled_balance) AS reconed_baln "
+                  "    FROM gncCheckpoint "
+                  "    WHERE accountGuid='");
    p = guid_to_string_buff (chk->account_guid, p);
-   p = stpcpy (p, "' AND commodity='");
+   p = stpcpy (p, "'   AND commodity='");
    p = stpcpy (p, chk->commodity);
-   p = stpcpy (p, "' AND date_start <'");
-   p = gnc_timespec_to_iso8601_buff (chk->date_start, p);
-   p = stpcpy (p, "' ORDER BY date_start DESC LIMIT 1;");
+   p = stpcpy (p, "'   AND date_end <'");
+   p = gnc_timespec_to_iso8601_buff (chk->date_end, p);
+   p = stpcpy (p, "';");
    SEND_QUERY (be,be->buff, );
 
    i=0; nrows=0;
@@ -264,9 +265,9 @@
          }
          if (0 < nrows )
          {
-            chk->balance = atoll(DB_GET_VAL("balance", j));
-            chk->cleared_balance = atoll(DB_GET_VAL("cleared_balance", j));
-            chk->reconciled_balance = atoll(DB_GET_VAL("reconciled_balance", j));
+            chk->balance = atoll(DB_GET_VAL("baln", j));
+            chk->cleared_balance = atoll(DB_GET_VAL("cleared_baln", j));
+            chk->reconciled_balance = atoll(DB_GET_VAL("reconed_baln", j));
          }
       }
 
@@ -278,53 +279,64 @@
 }
 
 /* ============================================================= */
-/* get checkpoint value for all accounts */
+/* get checkpoint value for one accounts */
 
 void
-pgendGroupGetAllCheckpoints (PGBackend *be, AccountGroup*grp)
+pgendAccountGetBalance (PGBackend *be, Account *acc, gint64 as_of_date)
 {
    Checkpoint chk;
-   GList *acclist, *node;
+   const gnc_commodity *com;
+   gint64 deno;
+   gnc_numeric baln;
+   gnc_numeric cleared_baln;
+   gnc_numeric reconciled_baln;
 
-   if (!be || !grp) return;
+   if (!be || !acc) return;
    ENTER("be=%p", be);
 
-/* XXX hack alert this is all wrong */
-   chk.date_start.tv_sec = time(0);
-   chk.date_start.tv_nsec = 0;
+   /* setup what we will match for */
+   chk.date_end.tv_sec = as_of_date;
+   chk.date_end.tv_nsec = 0;
+
+   com = xaccAccountGetCommodity(acc);
+   chk.commodity = gnc_commodity_get_unique_name(com);
+   chk.account_guid = xaccAccountGetGUID (acc);
+   chk.balance = 0;
+   chk.cleared_balance = 0;
+   chk.reconciled_balance = 0;
+
+   /* get the checkpoint */
+   pgendAccountGetCheckpoint (be, &chk);
+
+   /* set the account balances */
+   deno = gnc_commodity_get_fraction (com);
+   baln = gnc_numeric_create (chk.balance, deno);
+   cleared_baln = gnc_numeric_create (chk.cleared_balance, deno);
+   reconciled_baln = gnc_numeric_create (chk.reconciled_balance, deno);
 
-   acclist = xaccGroupGetSubAccounts (grp);
+   xaccAccountSetStartingBalance (acc, baln,
+                                     cleared_baln, reconciled_baln);
+   LEAVE("be=%p", be);
+}
+
+/* ============================================================= */
+/* get checkpoint value for all accounts */
 
+void
+pgendGroupGetAllBalances (PGBackend *be, AccountGroup *grp, 
+                             gint64 as_of_date)
+{
+   GList *acclist, *node;
+
+   if (!be || !grp) return;
+   ENTER("be=%p", be);
+
    /* loop over all accounts */
+   acclist = xaccGroupGetSubAccounts (grp);
    for (node=acclist; node; node=node->next)
    {
-      Account *acc;
-      const gnc_commodity *com;
-      gint64 deno;
-      gnc_numeric baln;
-      gnc_numeric cleared_baln;
-      gnc_numeric reconciled_baln;
-
-      /* setup what we will match for */
-      acc = (Account *) node->data;
-      com = xaccAccountGetCommodity(acc);
-      chk.commodity = gnc_commodity_get_unique_name(com);
-      chk.account_guid = xaccAccountGetGUID (acc);
-      chk.balance = 0;
-      chk.cleared_balance = 0;
-      chk.reconciled_balance = 0;
-
-      /* get the checkpoint */
-      pgendAccountGetCheckpoint (be, &chk);
-
-      /* set the account balances */
-      deno = gnc_commodity_get_fraction (com);
-      baln = gnc_numeric_create (chk.balance, deno);
-      cleared_baln = gnc_numeric_create (chk.cleared_balance, deno);
-      reconciled_baln = gnc_numeric_create (chk.reconciled_balance, deno);
-
-      xaccAccountSetStartingBalance (acc, baln,
-                                     cleared_baln, reconciled_baln);
+      Account *acc = (Account *) node->data;
+      pgendAccountGetBalance (be, acc, as_of_date);
    }
 
    g_list_free (acclist);
Index: gnucash/src/engine/sql/design.txt
diff -u gnucash/src/engine/sql/design.txt:1.10 gnucash/src/engine/sql/design.txt:1.11
--- gnucash/src/engine/sql/design.txt:1.10	Tue May 29 00:22:59 2001
+++ gnucash/src/engine/sql/design.txt	Thu May 31 13:24:12 2001
@@ -210,39 +210,4 @@
 ----------------------------
 nothing but junk below/test demo
 
-    UPDATE gnccheckpoint
-        SET balance = (gncsubtotalbalance (accountGuid, 
-                       date_start, date_start+360)),
-            cleared_balance = (gncsubtotalclearedbalance (accountguid, 
-                       date_start, date_start+360)),
-            reconciled_balance = (gncsubtotalreconedbalance (accountguid, 
-                       date_start, date_start+360))
-        WHERE accountguid='4c9cad7be044559705988c63ea7affc5';
-
-    UPDATE gnccheckpoint
-        SET cleared_balance = (gncsubtotalclearedbalance (accountguid, 
-                       date_start, date_start+360));
-
-    UPDATE gnccheckpoint
-        SET reconciled_balance = (gncsubtotalreconedbalance (accountguid, 
-                       date_start, date_start+360));
-
-
-
-
-UPDATE gnccheckpoint
-      SET balance = (SELECT sum(gncentry.valuenum)
-FROM gncentry, gnctransaction
-WHERE
-gncentry.accountguid = '4c9cad7be044559705988c63ea7affc5' AND
-gncentry.transguid = gnctransaction.transguid AND
-gnctransaction.date_posted BETWEEN date_xpoint AND
-date_xpoint + 360 )
-WHERE accountguid='111';
-
-
-
-INSERT INTO gnccheckpoint (accountguid, date_xpoint, commodity, balance)
-VALUES (111, '1997-01-01 12:00:00-05', 'FLOOP::GLOP', 0);
-
-
+SELECT sum(balance) FROM gncCheckpoint WHERE accountGuid='xx' AND date_start < 'xx'
Index: gnucash/src/engine/sql/kvp-sql.c
diff -u gnucash/src/engine/sql/kvp-sql.c:1.3 gnucash/src/engine/sql/kvp-sql.c:1.4
--- gnucash/src/engine/sql/kvp-sql.c:1.3	Tue Apr 17 04:32:08 2001
+++ gnucash/src/engine/sql/kvp-sql.c	Thu May 31 15:06:10 2001
@@ -437,6 +437,7 @@
 list_handler (PGBackend *be, PGresult *result, int j, gpointer data)
 {
    KVP_HANDLER_SETUP;
+   PERR ("not implemented");
    // kv = kvp_value_new_glist ();
    KVP_HANDLER_TAKEDOWN;
 }
@@ -451,13 +452,22 @@
    kf = pgendGetResults (be, TYPE##_handler, kf);	\
 }
 
+static gpointer 
+count_handler (PGBackend *be, PGresult *result, int j, gpointer data)
+{
+   int *cnt = (int *) data;
+   *cnt += atoi (DB_GET_VAL ("count", j));
+   return data;
+}
 
+
 kvp_frame * 
 pgendKVPFetch (PGBackend *be, const GUID *guid, kvp_frame *kf)
 {
    char * p;
    char iguid_str[40];
    int iguid = 0;
+   int count = 0;
    if (!be || !guid) return kf;
 
    ENTER (" ");
@@ -469,6 +479,15 @@
    iguid = pgendGetGUIDCacheID (be, guid);
    if (0 == iguid) return kf;
    snprintf (iguid_str, 40, "%d;", iguid);
+
+   /* save on some sql queries by avoiding kvp data fetches when 
+    * tehre is no data */
+   p = be->buff; *p = 0;
+   p = stpcpy (p, "SELECT count(*) FROM gncKVPValue WHERE iguid="); 
+   p = stpcpy (p, iguid_str);
+   SEND_QUERY (be,be->buff, kf);
+   pgendGetResults (be, count_handler, &count);	
+   if (0 == count) return kf;
 
    /* now troll the individual tables for data */
    GET_KVP(int64);
Index: gnucash/src/engine/sql/putil.h
diff -u gnucash/src/engine/sql/putil.h:1.5 gnucash/src/engine/sql/putil.h:1.6
--- gnucash/src/engine/sql/putil.h:1.5	Wed May  9 19:12:46 2001
+++ gnucash/src/engine/sql/putil.h	Thu May 31 13:24:12 2001
@@ -59,6 +59,7 @@
 {								\
    int rc;							\
    if (NULL == be->connection) return retval;			\
+   PINFO ("sending query %s", buff);				\
    rc = PQsendQuery (be->connection, buff);			\
    if (!rc)							\
    {								\
Index: gnucash/src/scm/commodity-utilities.scm
diff -u gnucash/src/scm/commodity-utilities.scm:1.21 gnucash/src/scm/commodity-utilities.scm:1.22
--- gnucash/src/scm/commodity-utilities.scm:1.21	Wed May 16 01:31:16 2001
+++ gnucash/src/scm/commodity-utilities.scm	Fri Jun  1 02:46:31 2001
@@ -1,6 +1,6 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; commodity-utilities.scm: Functions for handling different commodities.
-;; Copyright 2001 Christian Stimming <stimming@tu-harburg.de>
+;; Copyright 2001 Christian Stimming <stimming@tu-harburg.de>          
 ;; 
 ;; This program is free software; you can redistribute it and/or    
 ;; modify it under the terms of the GNU General Public License as   
@@ -590,6 +590,16 @@
 	 (gnc:convert-to-euro (gnc:gnc-monetary-commodity foreign)
 			      (gnc:gnc-monetary-amount foreign))))))
 
+
+;; A trivial exchange function - if the "foreign" monetary amount
+;; and the domestic currency are the same, return the foreign 
+;; amount unchanged, otherwise return 0
+
+(define (gnc:exchange-if-same foreign domestic)
+  (if (gnc:commodity-equiv? (gnc:gnc-monetary-commodity foreign) domestic)
+      foreign
+      #f))
+
 ;; This one returns the ready-to-use function for calculation of the
 ;; exchange rates. The returned function takes a <gnc-monetary> and
 ;; the <gnc:commodity*> domestic-commodity, exchanges the amount into
@@ -597,19 +607,23 @@
 (define (gnc:make-exchange-function exchange-alist)
   (let ((exchangelist exchange-alist))
     (lambda (foreign domestic)
-      (if foreign
-	  (or (gnc:exchange-by-euro foreign domestic #f)
-	      (gnc:make-gnc-monetary 
-	       domestic
-	       (let ((pair (assoc (gnc:gnc-monetary-commodity foreign) 
-				  exchangelist)))
-		 (if (not pair)
-		     (gnc:numeric-zero)
-		     (gnc:numeric-mul (gnc:gnc-monetary-amount foreign) 
-				      (cadr pair)
-				      (gnc:commodity-get-fraction domestic)
-				      GNC-RND-ROUND)))))
-	  #f))))
+      (begin
+	(gnc:debug "foreign: " foreign)
+	(gnc:debug "domestic: " domestic)
+	(if foreign
+	    (or (gnc:exchange-by-euro foreign domestic #f)
+		(gnc:exchange-if-same foreign domestic)
+		(gnc:make-gnc-monetary 
+		 domestic
+		 (let ((pair (assoc (gnc:gnc-monetary-commodity foreign) 
+				    exchangelist)))
+		   (if (not pair)
+		       (gnc:numeric-zero)
+		       (gnc:numeric-mul (gnc:gnc-monetary-amount foreign) 
+					(cadr pair)
+					(gnc:commodity-get-fraction domestic)
+					GNC-RND-ROUND)))))
+	  #f)))))
 
 ;; Helper for the gnc:exchange-by-pricalist* below. Exchange the
 ;; <gnc:monetary> 'foreign' into the <gnc:commodity*> 'domestic' by
@@ -668,6 +682,7 @@
 	 foreign domestic)
   (if (and (record? foreign) (gnc:gnc-monetary? foreign))
       (or (gnc:exchange-by-euro foreign domestic #f)
+	  (gnc:exchange-if-same foreign domestic)
 	   (gnc:exchange-by-pricedb-helper
 	    foreign domestic
 	    (gnc:pricedb-lookup-latest
@@ -689,6 +704,7 @@
   (if (and (record? foreign) (gnc:gnc-monetary? foreign)
 	   date)
       (or (gnc:exchange-by-euro foreign domestic date)
+	  (gnc:exchange-if-same foreign domestic)
 	   (gnc:exchange-by-pricedb-helper
 	    foreign domestic
 	    (gnc:pricedb-lookup-nearest-in-time
@@ -705,14 +721,22 @@
 ;; function returns a <gnc-monetary>.
 (define (gnc:exchange-by-pricealist-nearest
 	 pricealist foreign domestic date)
-  (if (and (record? foreign) (gnc:gnc-monetary? foreign)
-	   date (not (null? pricealist)))
+  (begin 
+    (gnc:debug "foreign " foreign)
+    (gnc:debug "domestic " domestic)
+    (gnc:debug "pricealist " pricealist)
+    
+    (if (and (record? foreign) (gnc:gnc-monetary? foreign)
+	   date)
       (or (gnc:exchange-by-euro foreign domestic date)
-	  (gnc:exchange-by-pricevalue-helper
-	   foreign domestic
-	   (gnc:pricealist-lookup-nearest-in-time
-	    pricealist (gnc:gnc-monetary-commodity foreign) date)))
-      #f))
+	  (gnc:exchange-if-same foreign domestic)
+	  (if (not (null? pricealist))
+	      (gnc:exchange-by-pricevalue-helper
+	       foreign domestic
+	       (gnc:pricealist-lookup-nearest-in-time
+		pricealist (gnc:gnc-monetary-commodity foreign) date))
+	      #f))
+      #f)))
 
        
 
Index: gnucash/src/scm/tip-of-the-day.scm
diff -u gnucash/src/scm/tip-of-the-day.scm:1.8 gnucash/src/scm/tip-of-the-day.scm:1.9
--- gnucash/src/scm/tip-of-the-day.scm:1.8	Thu Apr 12 18:03:41 2001
+++ gnucash/src/scm/tip-of-the-day.scm	Thu May 31 11:33:03 2001
@@ -69,7 +69,11 @@
 	#f))
 
 (define (gnc:current-tip-number)
-  (gnc:option-value (gnc:lookup-global-option "__tips" "current_tip_number")))
+  (let ((num (gnc:option-value
+              (gnc:lookup-global-option "__tips" "current_tip_number"))))
+    (if (<= (gnc:config-var-value-get gnc:*number-of-tips*) num)
+        (gnc:reset-tip-number))
+  (gnc:option-value (gnc:lookup-global-option "__tips" "current_tip_number"))))
 
 (define (gnc:get-current-tip)
   (_ (list-ref gnc:*tip-list* (gnc:current-tip-number))))
Index: gnucash/src/test/test-dom-converters1.c
diff -u gnucash/src/test/test-dom-converters1.c:1.11 gnucash/src/test/test-dom-converters1.c:1.13
--- gnucash/src/test/test-dom-converters1.c:1.11	Fri Mar 23 01:27:37 2001
+++ gnucash/src/test/test-dom-converters1.c	Thu May 31 16:01:00 2001
@@ -109,7 +109,8 @@
 
         if(test_spec2 == NULL)
         {
-            failure_args("dom_tree_to_timespec", __FILE__, __LINE__, "NULL return");
+            failure_args("dom_tree_to_timespec",
+                         __FILE__, __LINE__, "NULL return");
             printf("Node looks like:\n");
             xmlElemDump(stdout, NULL, test_node);
             printf("\n");
@@ -183,21 +184,25 @@
 test_dom_tree_to_gnc_numeric(void)
 {
     int i;
+
     for(i = 0; i < 20; i++)
     {
         gchar *message = NULL;
-        do_test_args(
-            (message = test_gnc_nums_internal(
-                get_random_gnc_numeric())) == NULL,
-            "dome_tree_to_gnc_numeric", __FILE__, __LINE__, message);
+
+        message = test_gnc_nums_internal(get_random_gnc_numeric());
+
+        do_test_args(message == NULL, "dom_tree_to_gnc_numeric",
+                     __FILE__, __LINE__, message);
     }
-    
+
     {
         gchar *message = NULL;
-        do_test_args(
-            (message = test_gnc_nums_internal(
-                gnc_numeric_create(18768786810, 100000))) == NULL,
-            "gnc_num 18768786810/100000", __FILE__, __LINE__, message);
+
+        message = test_gnc_nums_internal
+          (gnc_numeric_create(18768786810, 100000));
+
+        do_test_args(message == NULL, "gnc_num 18768786810/100000",
+                     __FILE__, __LINE__, message);
     }
 }
 
@@ -211,13 +216,13 @@
         GUID *test_guid1;
         GUID *test_guid2;
         xmlNodePtr test_node;
-        
+
         test_guid1 = get_random_guid();
-        
+
         if (!(test_node = guid_to_dom_tree("test-guid", test_guid1)))
         {
 	     failure_args("guid_to_dom_tree", __FILE__, __LINE__, 
-                         "conversion to dom tree failed");
+                          "conversion to dom tree failed");
         }
 
         test_guid2 = dom_tree_to_guid(test_node);