Hi all,

The discussions about the unit tests and the buried headers are pretty
advanced and I'm optimistic over the decisions taken so far.

I missed a discussion about the intenger types support so I would like to
start with some ideas brought by my current experiences using soci. I'll
try to be brief as possible.

First, there's the question of the C++03 support.
IMO, soci 4.0.0 needs to be a C++03 library with some (many?) optional
C++11 features (much like the boost-based ones). The more compatibility it
gets, the bigger our community will be.

Regarding the implementation of the integer types support for C++03 we
could rely on an existing stdint.h or provide a copy of it where required
(which is the case of Visual Studio 2005/2008) or we can use only the
native integer types with some additional code to detect their sizes (doing
part of what stdint.h does). I would rather the first option.

For mapping the backend types into the C++ ones, we need to consider
initially which kind of conversions we want: strict, compatible or
permissive.

Strict (same as the current soci::row): only database types with the same
capacity - data size or number of digits - and the same signedness of the
requested C++ integer type (e.g. std::int32_t = integer).
Compatible (same as the current soci::use?): database types with same
capacity or less of the requested C++ integer type (e.g. std::int32_t =
boolean/smallint/integer). Unsigned database types can be used with C++ signed
types with greater capacity (e.g. std::int32_t = 'unsigned' smallint).
Permissive (same as the current soci::into?): database **values** are
exchanged with any requested C++ integer type as far the value don't
get modified by the conversion, including char/varchar values (e.g. "SELECT
1" could be any C++ integer type).

Now, I want to extend this discussion even further. Let's do an exercise of
applying strict/compatible/permissive rules to all database types.

boolean:
strict - only C++ bool.
compatible - plus any C++ integer type.
permissive - plus strings.

real/float/double:
strict - only C++ float/double with the respective capacity.
compatible - plus all C++ integer types for sending values to the database.
C++ float-point types can also be used with integer database types.
permissive - plus all C++ integer types for receiving values with no
decimal part, plus strings.

numeric/decimal:
strict - an equivalent C++ type must be provided.
compatible - precision and scale are take into account and C++ integer and
float-point types with the proper capacity can be accepted. An equivalent
C++ type can also be used with integer or float-point database types
if the capacity and scale are big enough.
permissive - value is exchanged with any C++ numeric type as far the value
don't get modified by the conversion, plus strings.

char/varchar/nchar/nvarchar:
strict - only std::string (and maybe std::wstring).
compatible - plus any C++ numeric type or bool which gets converted to
string and it's sent to the database.
permissive - values containing numerical data - digits, sign, decimal
separator, etc. - gets converted to any C++ numeric type or bool as far the
value don't get modified by the conversion.

date/timestamp:
strict - an equivalent C++ data must be provided (same range).
compatible - plus an existing C++ time type (std tm or time_t).
permissive - any C++ integer type big enough to hold the time offset (or
epoch), plus strings.

bit/bitvar (and maybe blob?):
strict - an equivalent C++ type must be provided.
compatible - vector or string (with null chars) can hold the data.
permissive - any type would work (will be memcpy'd).

There's also a number of specific types for each backed I would
not consider initially.

It's important to say soci already apply most  of these
conversion rules according to the backend implementation, I just named them.

One can say the strict conversion is the 'most correct' but in the real
world checking back and forth the database types and picking the exact C++
equivalent all the time can be annoying. It's also more subject to
be broken by any small change to the database, because an exception is
thrown if the types don't match.

I would say the compatible conversion is 'conceptually right'. You don't to
worry much  if the type you selected has the exactly same type but you know
it is able to hold the values you want. An exception is throw only if the
destination type (either C++ or database) isn't big enough to hold all
values of the requested type.

The permissive conversion gets 'the job done'. Very flexible and relaxed,
you only get an exception if the conversion mess with the value.

Every model presented here has its pros and cons, so I propose soci to
support all of them and let the user decide at compile-time which one is
the most adequate.

There's also the possibility of a fourth type of conversion: forced. Where
the value is returned with the requested type even if data is lost during
the conversion. But I don't think soci should be responsible for such
thing. User must use the proper casts for such situations.

There's a number of ways of implementing the present proposal but I would
like to hear from all involved people any opinions and question about this
very early draft presented in this mail.

Best regards,
Ricardo Andrade
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
soci-devel mailing list
soci-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/soci-devel

Reply via email to