[odb-users] odb-2.2.1: calling db->persist() twice on the same
instance results in two database entries
Hugo.Mildenberger at web.de
Hugo.Mildenberger at web.de
Sat Mar 2 06:11:16 EST 2013
On Sat, 2 Mar 2013 11:21:50 +0100
Hugo.Mildenberger at web.de wrote:
> ODB creates two copies of the same instance in the database if db->persist() was called twice on it. I looked up the documentation but did not found this being documented behaviour. Perhaps I missed something important here? I had expected db->persist() throwing an exception in this case.
When analysing this problem using gdb, the reason appears to be that odb::database::persist() unconditionally passes "DEFAULT" instead of inserting the already known value for 'id' as it was returned from previous call to persist(). Consequently, st.execute() will never fail for a duplicate entry and thus the exception returned by "object_already_persistent()" will never been thrown, well, except for errors of a very different nature.
(gdb) bt
#0 odb::access::object_traits_impl<cif::imp::telecom, (odb::database_id)2>::persist (db=..., obj=...)
at odb/telecom-imp-odb.cxx:446
#1 0x00000000004033b3 in odb::database::persist_<cif::imp::telecom, (odb::database_id)5> (this=0x1cbbf50, obj=...)
at /usr/include/odb/database.txx:37
#2 0x000000000040329d in odb::database::persist<cif::imp::telecom> (this=0x1cbbf50, obj=...)
at /usr/include/odb/database.ixx:78
#3 0x0000000000402cc6 in main (argc=1, argv=0x3aeb88f1b68) at telecom.cxx:24
(gdb) list telecom-imp-odb.cxx:446
441 sts.insert_image_version (im.version);
442 imb.version++;
443 }
444
445 insert_statement& st (sts.persist_statement ());
446 if (!st.execute ())
447 throw object_already_persistent ();
448
449 obj._id = static_cast< id_type > (st.id ());
450
(gdb) print obj
$2 = (odb::access::object_traits<cif::imp::telecom>::object_type &) @0x3aeb88f19c0: {_type = "email", _priority = "0",
_uri = "sombody.1 at example.com", _purpose = "private", _id = 4}
(gdb) print st
$3 = (
odb::pgsql::insert_statement &) @0x1cc6fb0: {<odb::pgsql::statement> = {<odb::statement> = {<odb::details::shared_base> = {counter_ = 1, callback_ = 0x0}, _vptr.statement = 0x36ab19a1490 <vtable for odb::pgsql::insert_statement+16>},
conn_ = @0x1cbc120, name_copy_ = "",
name_ = 0x408290 <odb::access::object_traits_impl<cif::imp::telecom, (odb::database_id)2>::persist_statement_name> "cif_imp_telecom_persist", text_copy_ = "",
text_ = 0x408360 <odb::access::object_traits_impl<cif::imp::telecom, (odb::database_id)2>::persist_statement> "INSERT INTO \"telecom\" (\"type\",\"priority\",\"uri\",\"purpose\",\"id\") VALUES ($1,$2,$3,$4,DEFAULT) RETURNING \"id\"",
deallocated_ = false}, param_ = @0x1cc7348, native_param_ = @0x1cc7420, returning_ = true, id_ = 4}
More information about the odb-users
mailing list