diff options
author | Christoph Dittmann <github@christoph-d.de> | 2021-01-30 14:32:17 +0100 |
---|---|---|
committer | Martin Michlmayr <tbm@cyrius.com> | 2021-01-30 23:44:58 +0800 |
commit | b155f8928c6a33af42f859b27c83639b72517f5e (patch) | |
tree | 4b5d19cda86c2fc5b3786541c02326dea68f986c /src/commodity.cc | |
parent | 2dae3bbedcdf55983d23fc90bb36111c7eb68fc7 (diff) | |
download | fork-ledger-b155f8928c6a33af42f859b27c83639b72517f5e.tar.gz fork-ledger-b155f8928c6a33af42f859b27c83639b72517f5e.tar.bz2 fork-ledger-b155f8928c6a33af42f859b27c83639b72517f5e.zip |
compare_by_commodity: Always return the result of the recursive call
Commit 501fbc08ae5493db77bb34f4c4fbe1f3a3bc14e3 changed the behavior
of this function to not return the "equal" result (==0) from the
recursive call. Previously, the function returned the result of the
recursive call unconditionally.
The current behavior causes an assertion error for certain
postings. The regression test added in this commit shows such a
posting.
I found through Travis CI that the old behavior was incomplete and
caused unstable orderings, so reverting to the old behavior doesn't
work. Instead, this change adds a fallback: If the recursive call that
compares the prices numerically returns "equal", then compare the
prices with their original commodity as a tie breaker.
This commit does not change any existing ordering, it only adds
deterministic ordering in a case that currently triggers an assertion
error.
This fixes issue #1998.
Diffstat (limited to 'src/commodity.cc')
-rw-r--r-- | src/commodity.cc | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/src/commodity.cc b/src/commodity.cc index bdf6ee54..ebe388c8 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -465,18 +465,23 @@ int commodity_t::compare_by_commodity::operator()(const amount_t * left, amount_t rightprice(*arightcomm.details.price); if (leftprice.commodity() != rightprice.commodity()) { - // Since we have two different amounts, there's really no way - // to establish a true sorting order; we'll just do it based - // on the numerical values. - leftprice.clear_commodity(); - rightprice.clear_commodity(); + // Since we have two different amounts, there's really no way to + // establish a true sorting order; we'll just do it based on the + // numerical values, before falling back to comparing the prices + // with their original commodity. + amount_t leftpricenumeric(leftprice); + amount_t rightpricenumeric(rightprice); + leftpricenumeric.clear_commodity(); + rightpricenumeric.clear_commodity(); DEBUG("commodity.compare", "both have price, commodities don't match, recursing"); - int cmp2 = commodity_t::compare_by_commodity()(&leftprice, &rightprice); + int cmp2 = commodity_t::compare_by_commodity()(&leftpricenumeric, &rightpricenumeric); if (cmp2 != 0) { DEBUG("commodity.compare", "recursion found a disparity"); return cmp2; } + DEBUG("commodity.compare", "recursion found no difference, comparing prices with commodity"); + return commodity_t::compare_by_commodity()(&leftprice, &rightprice); } else { if (leftprice < rightprice) { DEBUG("commodity.compare", "left price is less"); |