You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When specializing type_conversion<>, is the to_base method required to set the indicator equal to some value? The example in the documentation sets ind = i_ok, but I want to know if setting the indicator is required or not.
Is the indicator in to_base an input and output variable, or only an output variable?
If the indicator is only an output variable, then when client code calls soci::use(myType, i_null) won't the i_null be ignored if the user-defined type doesn't represent a null value?
I will try to illustrate the problem implied in question 3 using the following code:
namespacesoci
{
template <>
structtype_conversion<MyInt>
{
typedefint base_type;
staticvoidfrom_base(int i, indicator ind, MyInt & mi)
{
// ... not important
}
staticvoidto_base(const MyInt & mi, int & i, indicator & ind)
{
i = mi.get();
ind = i_ok;
}
};
}
Code that wants to store MyInt in the database:
MyInt myInt(1);
soci::indicator ind = soci::i_null;
soci::session db;
db << "INSERT INTO foo (i) VALUES (:myInt)", soci::use(myInt, ind);
In the above code, what is the expected behavior? Should "NULL" be inserted, or should "1"? Currently, the above code results in "1" being inserted, even though the indicator was set to i_null. This is caused by the fact that to_base always sets the indicator to i_ok, even when it was explicitly set to i_null by the calling code.
One way to fix this issue would be to check ind in to_base to make sure the client code didn't set it to i_null:
staticvoidto_base(const MyInt & mi, int & i, indicator & ind)
{
if (ind != i_null) {
i = mi.get();
ind = i_ok;
}
}
This works fine, until the client code doesn't use an indicator:
MyInt myInt(1);
soci::session db;
db << "INSERT INTO foo (i) VALUES (:myInt)", soci::use(myInt);
Now, you will get undefined behavior because the indicator passed to to_base can come from soci::conversion_use_type::ind_, which is referencing soci::conversion_use_type::ownInd_, which was doesn't appear to be explicitly set when the client code used soci::use(T) instead of soci::use(T, indicator). This means that ownInd_ might be uninitialized. I see in my program that sometimes it is i_null and other times it is i_ok, which causes the exact same piece of client code to behave in different ways depending on which garbage value ownInd_ gets initialized to.
The text was updated successfully, but these errors were encountered:
@creste sorry for delay, but haven't had time to compile a comprehensive answer to your question, a very interesting issue, by the way.
I have been trying to reach Maciej about original design background, if he replies it may clarify a lot.
Meanwhile, a brief answer to the three questions based on my own understanding. So, AFAIU:
Yes, I'd expect indicator must be set or we decide explicitly on some default value and related behaviour.
It is output variable.
I'd expect, in soci::use(myType, i_null) that the value is ignored and, presumably, SOCI assigns SQL NULL to corresponding placeholder in query. I understand that the indicator correspondence with semantic of SQL NULL, thus wherever user sets soci::i_null, s/he means SQL NULL.
But, all these needs to be verified, either by Maciej's response or by inspection of current implementation and corrections applied if needed, so the semantics and behaviours are intuitive and consistent. I think this is important topic, but I have to complete the SOCI 3.2.0 release first.
I am not sure if this is a bug or just unclear documentation on http://soci.sourceforge.net/doc/exchange.html, so I'll start with some questions:
type_conversion<>
, is theto_base
method required to set the indicator equal to some value? The example in the documentation setsind = i_ok
, but I want to know if setting the indicator is required or not.to_base
an input and output variable, or only an output variable?soci::use(myType, i_null)
won't thei_null
be ignored if the user-defined type doesn't represent a null value?I will try to illustrate the problem implied in question 3 using the following code:
Code that wants to store MyInt in the database:
In the above code, what is the expected behavior? Should "NULL" be inserted, or should "1"? Currently, the above code results in "1" being inserted, even though the indicator was set to
i_null
. This is caused by the fact thatto_base
always sets the indicator toi_ok
, even when it was explicitly set toi_null
by the calling code.One way to fix this issue would be to check
ind
into_base
to make sure the client code didn't set it toi_null
:This works fine, until the client code doesn't use an indicator:
Now, you will get undefined behavior because the indicator passed to
to_base
can come fromsoci::conversion_use_type::ind_
, which is referencingsoci::conversion_use_type::ownInd_
, which was doesn't appear to be explicitly set when the client code usedsoci::use(T)
instead ofsoci::use(T, indicator)
. This means thatownInd_
might be uninitialized. I see in my program that sometimes it isi_null
and other times it isi_ok
, which causes the exact same piece of client code to behave in different ways depending on which garbage valueownInd_
gets initialized to.The text was updated successfully, but these errors were encountered: