Hello Tommi,

Thanks very much for reviewing this.

> >
> > I've tweaked it to try to detect overflow errors, and re-ran
> > the tests with the 4 databases.
> >
> > Also I tweaked it to use std::iostream::peek() in order to
> > try to avoid reading eof().
> >
> > I wasn't sure if we should throw std::overflow_error
> > when reading Decimals from an std::istream, instead
> > I just set the fail bit.
> >
>
> On Sun, 2 Sep 2007 18:26:05 +0200
> Tommi Mäkitalo <[EMAIL PROTECTED]> wrote:
> Setting fail bit in istream is the right thing to do.

Great, thanks.

> But tntdb::Decimal::getInteger<IntegerType>() should throw an 
> overflow_error.

I try to do that in the svn_diff_tntdb_decimal_sep_2_2007_2.txt
diffs I emailed you, however in the next update I will change
it to also throw std::overflow_error if (flags & (infinity | NaN)).
 
> But I would like to strip down the class a little. Do a database
> library really need input and output operators for iostream for the
> Decimal-type?

I think the answer is yes, as:

- SQLite, MySQL and PostgreSQL require the decimal number to be
written to a string in order to write it into the database.

- SQLite, MySQL and PostgreSQL require the decimal number to be
read from a string in order to write it into the database.

So the only choice to make is whether to only perform input and
output from strings, or from iostreams.  I was of course trying
to write code to fit into the existing tntdb library code.
The other number types are read and written from iostreams, so
I coded Decimal to use iostreams.

For example, for PostgreSQL the decimal numbers are read from the
database along with the other number types in:

    template <typename T>
    T getValue(const std::string& s, const char* tname)
    {
      std::istringstream in(s);
      T ret;
      in >> ret;
      if (in.eof() || !in.fail())
        return ret;
      std::ostringstream msg;
      msg << "can't convert \"" << s << "\" to " << tname;
      throw TypeError(msg.str());
    }

The lines:

      if (in.eof() || !in.fail())
        return ret;

can probably be changed back to (I will run tests to check):

      if (in)
        return ret;

Since I tweeked Decimal::read() to use peek() to avoid reading eof.

> tntdb::Date, tntdb::Time and tntdb::DateTime are just
> very simple data holder. I would prefer that for tntdb::Decimal too.

I noticed that tntdb::Date, tntdb::Time and tntdb::DateTime instead
perform intput and output from strings.  I considered doing that
for Decimal, but:

- it seemed that it would be almost as difficult as reading and
writing from iostreams.

- Using iostreams fits in better with the code for reading and writing
numbers and other types to and from the databases.

- providing iostreams input and output operators is more flexible than
reading and writing from strings.
 
> It is not that easy to do that iostream-stuff right. What about
> decimal point? In germany we use a decimal comma. You don't use the
> locale correctly.

Thanks for pointing out that bug, I can try to fix that.

However I ran a few tests with MySQL 5.21 beta 21 and
PostgreSQL 8.2.4 with the environment settings:

goanna% env | egrep "(LC_|LANG)"
LANG=de_DE
LC_MONETARY=de_DE
LC_TIME=de_DE
LC_MESSAGES=de_DE
LC_CTYPE=de_DE
LC_COLLATE=de_DE
LC_NUMERIC=de_DE
goanna% date
Montag,  3. September 2007, 21:03:46 Uhr EST
goanna%

and mysql and psql both still print output in English
and numeric/decimal values with . as the decimal point.

> Why do I need print flags in the decimal class?
> Tntdb does not need that. It is useless.

The print flags:

enum
{
  infinityShort,   // Affects output only, print Inf or -Inf.
  infinityLong,    // Affects output only, print Infinity or -Infinity
instead of Inf or -Inf. infinityTilde    // Affects output only, print
~ or -~ (as used in Oracle) instead of Inf or -Inf. };  

are for an obscure feature, the proposed ANSI C decimal
type can represent the values:

+Inf - positive infinity
-Inf - negative infinity
NaN - not a number

And some of the databases have limited support for some
of these.

The different databases and the C++ iostreams print out the
infinity values in different ways:

Oracle: -~ and +~

iostreams: -Inf and +Inf

It is easy when reading, just accept any of these formats.

However when outputing decimal values to the database, I was
trying to figure out how to output these values in the correct
formats.  Running some tests though I see that Oracle 10g r2,
MySQL 5.1 beta 21 and PostgreSQL 8.2.4 seem to have lots of
bugs with these values. So maybe it is useless.  I can remove
it if you like, and always print out these values as:

+Inf
-Inf
NaN

I wonder if I should just ignore any setting of ostream::width()
when outputting decimal numbers.  It seems difficult to figure
out what to do if the width is set, it may be too small.

> tntdb::Decimal::getBool does not make any sense. A decimal has
> nothing to do with bool. Why should a decimal has some special value,
> which is interpreted as false? You may do something like:
> 
>       tntdb::Decimal d = ...;
>       if (d == tntdb::Decimal(0, 0))
>       {
>               // d is zero
>       }
> 
> This is more readable than:
> 
>       tntdb::Decimal d = ...;
>       if (d.getBool())
>       {
>       }

OK we can remove getBool().

> I still like your idea with getInteger and getFloatingPoint as
> templates, but let us remove these iostream-stuff from tntdb.

It is probably not so easy to remove the iostream stuff as it
is being used to read and write the decimals from/to the database.
 
> There may be something like tntdbx::Decimal, which adds all that
> nifty things. You may then write:
> 
>       tntdb::Value v = ...;
>       std::cout << tntdbx::Decimal(v.getDecimal()) << std::endl;
> 
> The tntdb::Decimal will be very lightweight then.
> 
> Tommi

We can do that if you like, but you may have second thoughts
since the iostream stuff is used to read and write the
decimal numbers from/to the database.

I can modify it however you like.

Thanks very much.

Regards, Mark

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
Tntnet-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tntnet-general

Reply via email to