Ah I see, thanks. I changed the method to private and
const, and I get the compile-time error (see below).
I also noticed that if you declare an SSQLS with a
Nullable field in it's "key", you get a similar error:
../../cgi/handlers/admin_get_projects.cpp: In function
int cgi::<unnamed>::sql_compare_jproject(const
cgi::<unnamed>::jproject&, const
cgi::<unnamed>::jproject&) [with
mysqlpp::sql_dummy_type dummy = sql_dummy]:
../../cgi/handlers/admin_get_projects.cpp:23:
instantiated from here
../../cgi/handlers/admin_get_projects.cpp:23: error:
passing const mysqlpp::Null<short unsigned int,
mysqlpp::NullIsNull> as this argument of
mysqlpp::Null<Type, Behavior>::operator Type&() [with
Type = short unsigned int, Behavior =
mysqlpp::NullIsNull] discards qualifiers
../../cgi/handlers/admin_get_projects.cpp:23:
instantiated from here
../../cgi/handlers/admin_get_projects.cpp:23: error:
passing const mysqlpp::Null<short unsigned int,
mysqlpp::NullIsNull> as this argument of
mysqlpp::Null<Type, Behavior>::operator Type&() [with
Type = short unsigned int, Behavior =
mysqlpp::NullIsNull] discards qualifiers
/usr/local/include/mysql++/null.h: In member function
mysqlpp::Null<Type, Behavior>::operator Type&() [with
Type = short unsigned int, Behavior =
mysqlpp::NullIsNull]:
../../cgi/handlers/admin_get_projects.cpp:23:
instantiated from int
cgi::<unnamed>::sql_compare_jproject(const
cgi::<unnamed>::jproject&, const
cgi::<unnamed>::jproject&) [with
mysqlpp::sql_dummy_type dummy = sql_dummy]
../../cgi/handlers/admin_get_projects.cpp:23:
instantiated from here
/usr/local/include/mysql++/null.h:54: error:
template<class Type> mysqlpp::null_type::operator
Type() const is private
/usr/local/include/mysql++/null.h:209: error: within
this context
Now I agree having a NULL in a key is not what you
regularly want, but the error-message does not really
help. Maybe add a note to the documentation?
Also, I couldn't find in the documentation how to
compare two Nullable fields in an SSQLS (it gives a
compile-time error). After looking at the source-code
I found I can use the "is_null" and "data" members.
Cheers,
Andrej
--- Warren Young <mysqlpp@stripped> wrote:
> Andrej van der Zee wrote:
> >
> > But yes, declaring a constant:
> > const mysqlpp::Null<mysqlpp::sql_int_unsigned>
> > msr_null(mysqlpp::null);
>
> No, I meant change the operator method to be const:
>
> public:
> #if !defined(DOXYGEN_IGNORE)
> // Doxygen will not generate documentation for
> this section.
> - template <class Type> operator Type()
> + template <class Type> operator Type() const
> {
> throw BadNullConversion();
> return Type();
>
> This change will appear in the next release. I just
> wanted you to know
> you could easily change your copy to test it before
> then.
>
> > Still don't really understand why it doesn't work
> in a
> > "a?a:b" embedded statement
>
> Due to the data type conversions required in that
> statement, it was
> trying to call null_type::operator Type(), but
> mysqlpp::null is a const
> object, so it can only call it if the method is
> marked as const. It was
> an error for it to not be so marked before because
> it doesn't actually
> modify the null_type object.
>
> This bug has existed since at least 1.7.9, for what
> it's worth.
>
> I just realized something, however: if you apply
> this change and try to
> use the code you showed, it'll throw
> BadNullConversion. (Study the diff
> above.) This is really funny, actually. This
> operator exists to detect
> incorrect library use, but it was impossible to
> trigger it through the
> mysqlpp::null instance. Sigh.... :)
>
> The problem is that for this:
>
> unsigned msr_id = ...; // some value
> ssqls.nullable_member = msr_id ? msr_id :
> mysqlpp::null;
>
> to be a consistent statement in C++, the compiler
> has to coerce all the
> data types to the same type. Having taken care of
> the constness issue,
> your compiler is now allowed to convert
> mysqlpp::null to unsigned int,
> but having done it, you will get an exception.
>
> Bottom line, the code looks like it should work, but
> it's not right.
> The more verbose way of writing it is correct
> because it uses the two
> rvalues in different contexts, so they don't have to
> be the same type:
>
> if (msr_id) {
> ssqls.nullable_member = msr_id;
> }
> else {
> ssqls.nullable_member = mysqlpp::null;
> }
>
> Perhaps the most compact, legal way to say this is:
>
> ssqls.nullable_member = msr_id;
> ssqls.nullable_member.is_null = !msr_id;
>
> Legal it is, but I don't know about sensible. It
> says that SQL null in
> this context is the same as zero or Boolean false.
> The point of SQL
> null is that it is equal to nothing else, so why use
> it here? Are you
> sure you aren't just using new features because
> they're there?
>
> As a result of this realization, I'm changing
> null_type so trying to do
> this results in a different compile time error than
> the one you got
> that's clearer. I get this with g++ 4.1.2:
>
> lib/null.h:55: error: template<class
> CannotConvertNullToAnyOtherDataType>
> mysqlpp::null_type::operator
> CannotConvertNullToAnyOtherDataType() const is
> private
>
> (Amusingly, the 'const' fix is still needed.)
>
> Also, I'm documenting this anti-pattern in the
> reference manual.
>
>
>
> --
> MySQL++ Mailing List
> For list archives: http://lists.mysql.com/plusplus
> To unsubscribe:
>
http://lists.mysql.com/plusplus?unsub=1
>
>
___________________________________________________________
Support the World Aids Awareness campaign this month with Yahoo! For Good
http://uk.promotions.yahoo.com/forgood/