r17988 - gnucash/trunk/src/report/report-system - Reports: Speed up the report infrastructure. Patch by Mike Alexander.
Charles Day
cedayiv at cvs.gnucash.org
Mon Mar 9 16:14:46 EDT 2009
Author: cedayiv
Date: 2009-03-09 16:14:46 -0400 (Mon, 09 Mar 2009)
New Revision: 17988
Trac: http://svn.gnucash.org/trac/changeset/17988
Modified:
gnucash/trunk/src/report/report-system/html-acct-table.scm
gnucash/trunk/src/report/report-system/report-system.scm
gnucash/trunk/src/report/report-system/report-utilities.scm
Log:
Reports: Speed up the report infrastructure. Patch by Mike Alexander.
One set of changes speeds up the three functions in report-utilities.scm:
gnc:account-get-comm-balance-interval
gnc:accountlist-get-comm-balance-interval
gnc:accountlist-get-comm-balance-at-date
These can all be implemented as calls to
gnc:account-get-trans-type-balance-interval (with a minor change to it to
ignore the type parameter if it is #f) and it is much faster since it does a
single query instead of a loop over an account list.
The other set of changes is in gnc:html-acct-table-add-accounts! in
html-acct-table.scm. This functions starts off by building a hash table of
account balances it cares about. The code to do this did a recursive loop over
the relevant accounts. I changed it to do a query to find the splits in the
accounts it cares about and build the hash table from them. This speeds it up
by a couple of orders of magnitude.
Modified: gnucash/trunk/src/report/report-system/html-acct-table.scm
===================================================================
--- gnucash/trunk/src/report/report-system/html-acct-table.scm 2009-03-09 20:07:51 UTC (rev 17987)
+++ gnucash/trunk/src/report/report-system/html-acct-table.scm 2009-03-09 20:14:46 UTC (rev 17988)
@@ -638,75 +638,72 @@
;; the following function was adapted from html-utilities.scm
;;
- ;;
- ;; there's got to be a prettier way to do this. maybe even make two
- ;; of these. The balance-mode is only used by trial-balance.scm. so
- ;; make two versions of this animal, one that cares about balance-mode
- ;; one that doesn't. then check for a balance-mode !'post-closing and
- ;; call the right one. later.
- (define (get-balance-nosub-mode account start-date end-date)
- (let* ((post-closing-bal
- (if start-date
- (gnc:account-get-comm-balance-interval
- account start-date end-date #f)
- (gnc:account-get-comm-balance-at-date
- account end-date #f)))
- (closing (lambda(a)
- (gnc:account-get-trans-type-balance-interval
- (list account) closing-pattern
- start-date end-date)
- )
- )
- (adjusting (lambda(a)
- (gnc:account-get-trans-type-balance-interval
- (list account) adjusting-pattern
- start-date end-date)
- )
- )
- )
- (cond
- ((equal? balance-mode 'post-closing)
- post-closing-bal)
-
- ((equal? balance-mode 'pre-closing)
- (let* ((closing-amt (closing account))
- )
- (post-closing-bal 'minusmerge closing-amt #f))
- post-closing-bal)
-
- ((equal? balance-mode 'pre-adjusting)
- (let* ((closing-amt (closing account))
- (adjusting-amt (adjusting account))
- ))
- (post-closing-bal 'minusmerge closing-amt #f)
- (post-closing-bal 'minusmerge adjusting-amt #f)
- post-closing-bal)
- (else (begin (display "you fail it")
- (newline))))
-
- )
- )
-
;; helper to calculate the balances for all required accounts
(define (calculate-balances accts start-date end-date get-balance-fn)
(define (calculate-balances-helper accts start-date end-date acct-balances)
(if (not (null? accts))
(begin
- ;; using the existing function that cares about balance-mode
- ;; maybe this should get replaces at some point.
- (hash-set! acct-balances (gncAccountGetGUID (car accts))
- (get-balance-fn (car accts) start-date end-date))
- (calculate-balances-helper (cdr accts) start-date end-date acct-balances)
- )
+ ;; using the existing function that cares about balance-mode
+ ;; maybe this should get replaces at some point.
+ (hash-set! acct-balances (gncAccountGetGUID (car accts))
+ (get-balance-fn (car accts) start-date end-date))
+ (calculate-balances-helper (cdr accts) start-date end-date acct-balances)
+ )
acct-balances)
)
-
- (calculate-balances-helper accts start-date end-date
- (make-hash-table 23))
- )
+ (define (calculate-balances-simple accts start-date end-date hash-table)
+ (define (merge-splits splits subtract?)
+ (for-each
+ (lambda (split)
+ (let* ((acct (xaccSplitGetAccount split))
+ (guid (gncAccountGetGUID acct))
+ (acct-comm (xaccAccountGetCommodity acct))
+ (shares (xaccSplitGetAmount split))
+ (hash (hash-ref hash-table guid)))
+; (gnc:debug "Merging split for " (xaccAccountGetName acct) " for "
+; (gnc-commodity-numeric->string acct-comm shares)
+; " into hash entry " hash)
+ (if (not hash)
+ (begin (set! hash (gnc:make-commodity-collector))
+ (hash-set! hash-table guid hash)))
+ (hash 'add acct-comm (if subtract?
+ (gnc-numeric-neg shares)
+ shares))))
+ splits))
+ (merge-splits (gnc:account-get-trans-type-splits-interval
+ accts #f start-date end-date)
+ #f)
+ (cond
+ ((equal? balance-mode 'post-closing) #t)
+
+ ((equal? balance-mode 'pre-closing)
+ (merge-splits (gnc:account-get-trans-type-splits-interval
+ accts closing-pattern start-date end-date)
+ #t))
+
+ ((equal? balance-mode 'pre-adjusting)
+ (merge-splits (gnc:account-get-trans-type-splits-interval
+ accts closing-pattern start-date end-date)
+ #t)
+ (merge-splits (gnc:account-get-trans-type-splits-interval
+ accts adjusting-pattern start-date end-date)
+ #t))
+ (else (begin (display "you fail it")
+ (newline))))
+ hash-table
+ )
+
+ (if get-balance-fn
+ (calculate-balances-helper accts start-date end-date
+ (make-hash-table 23))
+ (calculate-balances-simple accts start-date end-date
+ (make-hash-table 23))
+ )
+ )
+
(define (traverse-accounts! accts acct-depth logi-depth new-balances)
(define (use-acct? acct)
@@ -900,7 +897,8 @@
) ;; end of definition of traverse-accounts!
;; do it
- (traverse-accounts! toplvl-accts 0 0 (calculate-balances accounts start-date end-date (or get-balance-fn get-balance-nosub-mode)))
+ (traverse-accounts! toplvl-accts 0 0
+ (calculate-balances accounts start-date end-date get-balance-fn))
;; set the column-header colspan
(if gnc:colspans-are-working-right
Modified: gnucash/trunk/src/report/report-system/report-system.scm
===================================================================
--- gnucash/trunk/src/report/report-system/report-system.scm 2009-03-09 20:07:51 UTC (rev 17987)
+++ gnucash/trunk/src/report/report-system/report-system.scm 2009-03-09 20:14:46 UTC (rev 17988)
@@ -663,6 +663,7 @@
(export gnc-commodity-collector-allzero?)
(export gnc:account-get-trans-type-balance-interval)
(export gnc:account-get-pos-trans-total-interval)
+(export gnc:account-get-trans-type-splits-interval)
(export gnc:double-col)
(export gnc:budget-get-start-date)
(export gnc:budget-account-get-net)
Modified: gnucash/trunk/src/report/report-system/report-utilities.scm
===================================================================
--- gnucash/trunk/src/report/report-system/report-utilities.scm 2009-03-09 20:07:51 UTC (rev 17987)
+++ gnucash/trunk/src/report/report-system/report-utilities.scm 2009-03-09 20:14:46 UTC (rev 17988)
@@ -624,39 +624,22 @@
;; the version which returns a commodity-collector
(define (gnc:account-get-comm-balance-interval
account from to include-children?)
- ;; Since this function calculates a balance difference it has to
- ;; subtract the balance of the previous day's end (from-date)
- ;; instead of the plain date.
- (let ((this-collector (gnc:account-get-comm-balance-at-date
- account to include-children?)))
- (gnc-commodity-collector-minusmerge
- this-collector
- (gnc:account-get-comm-balance-at-date
- account
- (gnc:timepair-end-day-time (gnc:timepair-previous-day from))
- include-children?))
- this-collector))
+ (let ((account-list (if include-children?
+ (let ((sub-accts (gnc-account-get-descendants-sorted account)))
+ (if sub-accts
+ (append (list account) sub-accts)
+ (list account)))
+ (list account))))
+ (gnc:account-get-trans-type-balance-interval account-list #f from to)))
;; This calculates the increase in the balance(s) of all accounts in
;; <accountlist> over the period from <from-date> to <to-date>.
;; Returns a commodity collector.
(define (gnc:accountlist-get-comm-balance-interval accountlist from to)
- (let ((collector (gnc:make-commodity-collector)))
- (for-each (lambda (account)
- (gnc-commodity-collector-merge
- collector (gnc:account-get-comm-balance-interval
- account from to #f)))
- accountlist)
- collector))
+ (gnc:account-get-trans-type-balance-interval accountlist #f from to))
(define (gnc:accountlist-get-comm-balance-at-date accountlist date)
- (let ((collector (gnc:make-commodity-collector)))
- (for-each (lambda (account)
- (gnc-commodity-collector-merge
- collector (gnc:account-get-comm-balance-at-date
- account date #f)))
- accountlist)
- collector))
+ (gnc:account-get-trans-type-balance-interval accountlist #f #f date))
;; utility function - ensure that a query matches only non-voids. Destructive.
(define (gnc:query-set-match-non-voids-only! query book)
@@ -720,40 +703,21 @@
;; Sums up any splits of a certain type affecting a set of accounts.
;; the type is an alist '((str "match me") (cased #f) (regexp #f))
+;; If type is #f, sums all splits in the interval
(define (gnc:account-get-trans-type-balance-interval
account-list type start-date-tp end-date-tp)
- (let* ((query (qof-query-create-for-splits))
- (splits #f)
- (get-val (lambda (alist key)
- (let ((lst (assoc-ref alist key)))
- (if lst (car lst) lst))))
- (matchstr (get-val type 'str))
- (case-sens (if (get-val type 'cased) #t #f))
- (regexp (if (get-val type 'regexp) #t #f))
- (total (gnc:make-commodity-collector))
- )
- (qof-query-set-book query (gnc-get-current-book))
- (gnc:query-set-match-non-voids-only! query (gnc-get-current-book))
- (xaccQueryAddAccountMatch query account-list QOF-GUID-MATCH-ANY QOF-QUERY-AND)
- (xaccQueryAddDateMatchTS
- query
- (and start-date-tp #t) start-date-tp
- (and end-date-tp #t) end-date-tp QOF-QUERY-AND)
- (xaccQueryAddDescriptionMatch
- query matchstr case-sens regexp QOF-QUERY-AND)
-
- (set! splits (qof-query-run query))
+ (let* ((total (gnc:make-commodity-collector)))
(map (lambda (split)
- (let* ((shares (xaccSplitGetAmount split))
- (acct-comm (xaccAccountGetCommodity
- (xaccSplitGetAccount split)))
- )
- (gnc-commodity-collector-add total acct-comm shares)
- )
- )
- splits
+ (let* ((shares (xaccSplitGetAmount split))
+ (acct-comm (xaccAccountGetCommodity
+ (xaccSplitGetAccount split)))
+ )
+ (gnc-commodity-collector-add total acct-comm shares)
+ )
+ )
+ (gnc:account-get-trans-type-splits-interval
+ account-list type start-date-tp end-date-tp)
)
- (qof-query-destroy query)
total
)
)
@@ -820,6 +784,35 @@
)
)
+;; Return the splits that match an account list, date range, and (optionally) type
+;; where type is defined as an alist '((str "match me") (cased #f) (regexp #f))
+(define (gnc:account-get-trans-type-splits-interval
+ account-list type start-date-tp end-date-tp)
+ (let* ((query (qof-query-create-for-splits))
+ (splits #f)
+ (get-val (lambda (alist key)
+ (let ((lst (assoc-ref alist key)))
+ (if lst (car lst) lst))))
+ (matchstr (get-val type 'str))
+ (case-sens (if (get-val type 'cased) #t #f))
+ (regexp (if (get-val type 'regexp) #t #f))
+ )
+ (qof-query-set-book query (gnc-get-current-book))
+ (gnc:query-set-match-non-voids-only! query (gnc-get-current-book))
+ (xaccQueryAddAccountMatch query account-list QOF-GUID-MATCH-ANY QOF-QUERY-AND)
+ (xaccQueryAddDateMatchTS
+ query
+ (and start-date-tp #t) start-date-tp
+ (and end-date-tp #t) end-date-tp QOF-QUERY-AND)
+ (if type (xaccQueryAddDescriptionMatch
+ query matchstr case-sens regexp QOF-QUERY-AND))
+
+ (set! splits (qof-query-run query))
+ (qof-query-destroy query)
+ splits
+ )
+ )
+
;; utility to assist with double-column balance tables
;; a request is made with the <req> argument
;; <req> may currently be 'entry|'debit-q|'credit-q|'zero-q|'debit|'credit
More information about the gnucash-changes
mailing list