From finjulhich at gmail.com Sun Feb 2 17:59:19 2025 From: finjulhich at gmail.com (MM) Date: Sun Feb 2 17:59:49 2025 Subject: [odb-users] base class before derived class Message-ID: Hello, odb had introduced a defensive failure when the order of base classes and derived was not expected with regards to when the class is defined, and when the pragma db object definition is called. I'm encountering this error. Is there a general statement that can be made to avoid this failure? I have the base class, derived, and then later pragmas invoked... Of course I will put a example snippet, but what is the general idea? From boris at codesynthesis.com Tue Feb 4 02:47:08 2025 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Feb 4 02:45:51 2025 Subject: [odb-users] postgresql data change callback In-Reply-To: References: Message-ID: MM writes: > If my application, while having a connection to a postgresql database, > wishes to be notified when data in a persistent container is changed by > another application, is there any "notify" mechanism that odb supports? No, no such mechanism at the moment. > If not, the advice would be to use native libpq library facilities for such > a feature? Correct. One potential issue that I see is that you will presumably have to hold the connection while you are waiting for the notification, which may not scale very well, especially in PG with its connection-per-process model. Maybe you could dedicate one shared connection to waiting for all the notifications or some such. From boris at codesynthesis.com Tue Feb 4 07:37:42 2025 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Feb 4 07:36:27 2025 Subject: [odb-users] Lazy pointers, yet agian In-Reply-To: <117511738229627@mail.yandex.ru> References: <117511738229627@mail.yandex.ru> Message-ID: ????? ???????? writes: > The "isNull() - loaded()" truth table that's in the sources and which > was already cited on this list a while ago is confusing to me: > > // isNull() loaded() > // > 1. true true NULL pointer to transient object > 2. false true valid pointer to persistent object > 3. true false unloaded pointer to persistent object > 4. false false valid pointer to transient object > > Based on what I've been able to deduce from reading the sources the > lazy pointer consists of two parts - eager part and lazy part. > The pointer is considered NULL if both these parts are null, the > pointer is considered loaded, if either they are both null, or they > are both not null. Which leads to the conclusion that if the pointer is > NULL then it is necessarily loaded, and the 3 combination is > impossible. Am I missing something here? Hm, if #3 was not possible then a lazy pointer that cannot store an unloaded pointer to persistent object would not be very useful. And yet lazy_ptr is used quite a bit, so there is definitely some confusion somewhere, but I am not sure where. P.S., in the future can you please use an email client (e.g., gmail) that is able to send plain text messages so that we don't end up with garbage like this: https://codesynthesis.com/pipermail/odb-users/2025-January/005116.html From boris at codesynthesis.com Tue Feb 4 07:44:26 2025 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Feb 4 07:43:07 2025 Subject: [odb-users] postgres constraints (or triggers) In-Reply-To: References: Message-ID: MM writes: > I wish to ensure that the sum of a column across all rows always equals > 100%. Currently I ensure that at the application level before persistence. > postgresql CHECK constraint doesn't work for this but I believe a TRIGGER > may work before insert/update. There's no odb support for that is there? There is no ODB support for creating triggers but I don't think anything prevents you from creating one manually yourself. > Is it the advice to keep at user code in the application instead? There are different schools of thought on this: Some think that any processing that can be performed on the client side should be done there to reduce the load on the database. Others think it is better to perform it on the database in order to enforce consistent behavior. From boris at codesynthesis.com Tue Feb 4 07:47:24 2025 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Feb 4 07:46:06 2025 Subject: [odb-users] base class before derived class In-Reply-To: References: Message-ID: MM writes: > odb had introduced a defensive failure when the order of base classes and > derived was not expected with regards to when the class is defined, and > when the pragma db object definition is called. I am not sure what you mean, an example/reproducer would help clarify this. > Is there a general statement that can be made to avoid this failure? Not sure, but probably "base should be defined before derived"? From enmarantispam at gmail.com Mon Feb 17 17:56:15 2025 From: enmarantispam at gmail.com (NIkolai Marchenko) Date: Tue Feb 18 01:12:57 2025 Subject: [odb-users] any significant changes to threading model in 2.5? Message-ID: I am getting this error: /home/zeks/odbbuild/libodb-gcc-9/libodb-gcc-9/libodb-2.5.0/odb/transaction.cxx:340: virtual odb::connection& odb::transaction_impl::connection(odb::transaction_impl::database_type*): Assertion `db == 0 || db == &database_' failed. This happens modestly in thread workers, my code is keeping thread_local instance of odb::transaction obtained with db->begin(). Do I need to fix something obvious? This only started happening with 2.5, it was working fine before. Note: not ever ODB query fails, in fact all of my tests work as they are supposed to, but i am suddenly getting a ton of those errors in worker threads From boris at codesynthesis.com Tue Feb 18 04:38:57 2025 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Feb 18 04:37:38 2025 Subject: [odb-users] any significant changes to threading model in 2.5? In-Reply-To: References: Message-ID: NIkolai Marchenko writes: > I am getting this error: > > /home/zeks/odbbuild/libodb-gcc-9/libodb-gcc-9/libodb-2.5.0/odb/transaction.cxx:340: > virtual odb::connection& > odb::transaction_impl::connection(odb::transaction_impl::database_type*): > Assertion `db == 0 || db == &database_' failed. This is a "sanity check" that makes sure you don't use a transaction that was started on a different database instance. This check is actually new in 2.5.0, I see it's not present in 2.4.0. So maybe it is catching an error on your side? The only significant threading-related change in ODB 2.5.0 is that we have switched to C++11 threads. In ODB 2.4.0 we used POSIX threads on POSIX and Win32 threads on Windows. But I don't think this should matter, even if you are using the POSIX API for TLS. > This happens modestly in thread workers, my code is keeping thread_local > instance of odb::transaction obtained with db->begin(). It would be interesting to see if database_ points to a valid database instance. From enmarantispam at gmail.com Tue Feb 18 08:19:42 2025 From: enmarantispam at gmail.com (NIkolai Marchenko) Date: Tue Feb 18 08:29:58 2025 Subject: [odb-users] any significant changes to threading model in 2.5? In-Reply-To: References: Message-ID: Correct me if I am wrong: I was of the opinion that generating a new database object didn't do anything to an internal thread_local connection held by an odb::transaction instance . This was a basis of what I was doing in my code and it worked fine previously. In fact there are two distinct paths that are now causing issues that worked in 2.4: 1) Loading an internal lazy object in a separate thread via .load() compared to where the original outside lazy object was acquired 2) Trying to persist an object in an odbcallbackhook that creates a new database object, but still uses the same odb::transaction, since, inside my framework, when it sees that a thread_local odb::transaction is already loaded it doesn't try to open a new transaction, but still creates a new odb::database.. It's possible that both of those were mishandling of the library on my side that were never checked, but they have been working flawlessly for 2 years so now I am left scratching my head about what would be a correct path of dealing with it. On Tue, Feb 18, 2025 at 12:37?PM Boris Kolpackov wrote: > NIkolai Marchenko writes: > > > I am getting this error: > > > > > /home/zeks/odbbuild/libodb-gcc-9/libodb-gcc-9/libodb-2.5.0/odb/transaction.cxx:340: > > virtual odb::connection& > > odb::transaction_impl::connection(odb::transaction_impl::database_type*): > > Assertion `db == 0 || db == &database_' failed. > > This is a "sanity check" that makes sure you don't use a transaction that > was started on a different database instance. This check is actually new > in 2.5.0, I see it's not present in 2.4.0. So maybe it is catching an > error on your side? > > The only significant threading-related change in ODB 2.5.0 is that we > have switched to C++11 threads. In ODB 2.4.0 we used POSIX threads on > POSIX and Win32 threads on Windows. But I don't think this should matter, > even if you are using the POSIX API for TLS. > > > > This happens modestly in thread workers, my code is keeping thread_local > > instance of odb::transaction obtained with db->begin(). > > It would be interesting to see if database_ points to a valid database > instance. > From enmarantispam at gmail.com Tue Feb 18 18:08:12 2025 From: enmarantispam at gmail.com (NIkolai Marchenko) Date: Wed Feb 19 08:17:04 2025 Subject: [odb-users] any significant changes to threading model in 2.5? In-Reply-To: References: Message-ID: Fiddling with what I can do about this all I came across one point where this check is massively in the way and makes the code significantly more complicated. Where before you just needed to call .load() without caring about the new check and things just worked, you now have to write the construction like data = transaction.db()->load(data.objectId()); to ensure that you are not hitting this new check and getting asserted. this just makes code much more cumbersome and unintuitive On Tue, Feb 18, 2025 at 4:19?PM NIkolai Marchenko wrote: > Correct me if I am wrong: I was of the opinion that generating a new > database object didn't do anything to an internal thread_local connection > held by an odb::transaction instance . This was a basis of what I was doing > in my code and it worked fine previously. > > In fact there are two distinct paths that are now causing issues that > worked in 2.4: > > 1) Loading an internal lazy object in a separate thread via .load() > compared to where the original outside lazy object was acquired > 2) Trying to persist an object in an odbcallbackhook that creates a new > database object, but still uses the same odb::transaction, since, inside my > framework, when it sees that a thread_local odb::transaction is already > loaded it doesn't try to open a new transaction, but still creates a new > odb::database.. > > It's possible that both of those were mishandling of the library on my > side that were never checked, but they have been working flawlessly for 2 > years so now I am left scratching my head about what would be a correct > path of dealing with it. > > On Tue, Feb 18, 2025 at 12:37?PM Boris Kolpackov > wrote: > >> NIkolai Marchenko writes: >> >> > I am getting this error: >> > >> > >> /home/zeks/odbbuild/libodb-gcc-9/libodb-gcc-9/libodb-2.5.0/odb/transaction.cxx:340: >> > virtual odb::connection& >> > >> odb::transaction_impl::connection(odb::transaction_impl::database_type*): >> > Assertion `db == 0 || db == &database_' failed. >> >> This is a "sanity check" that makes sure you don't use a transaction that >> was started on a different database instance. This check is actually new >> in 2.5.0, I see it's not present in 2.4.0. So maybe it is catching an >> error on your side? >> >> The only significant threading-related change in ODB 2.5.0 is that we >> have switched to C++11 threads. In ODB 2.4.0 we used POSIX threads on >> POSIX and Win32 threads on Windows. But I don't think this should matter, >> even if you are using the POSIX API for TLS. >> >> >> > This happens modestly in thread workers, my code is keeping thread_local >> > instance of odb::transaction obtained with db->begin(). >> >> It would be interesting to see if database_ points to a valid database >> instance. >> > From enmarantispam at gmail.com Tue Feb 18 18:34:18 2025 From: enmarantispam at gmail.com (NIkolai Marchenko) Date: Wed Feb 19 08:17:04 2025 Subject: [odb-users] any significant changes to threading model in 2.5? In-Reply-To: References: Message-ID: In short: with the addition of this check .load() became unusable in any sort of delayed loading because now you have to *know* whether you are doing it in the same thread, which is just not realistic. On Wed, Feb 19, 2025 at 2:08?AM NIkolai Marchenko wrote: > Fiddling with what I can do about this all I came across one point where > this check is massively in the way and makes the code significantly more > complicated. Where before you just needed to call .load() without caring > about the new check and things just worked, you now have to write the > construction like > > data = transaction.db()->load(data.objectId()); > > to ensure that you are not hitting this new check and getting asserted. > this just makes code much more cumbersome and unintuitive > > On Tue, Feb 18, 2025 at 4:19?PM NIkolai Marchenko > wrote: > >> Correct me if I am wrong: I was of the opinion that generating a new >> database object didn't do anything to an internal thread_local connection >> held by an odb::transaction instance . This was a basis of what I was doing >> in my code and it worked fine previously. >> >> In fact there are two distinct paths that are now causing issues that >> worked in 2.4: >> >> 1) Loading an internal lazy object in a separate thread via .load() >> compared to where the original outside lazy object was acquired >> 2) Trying to persist an object in an odbcallbackhook that creates a new >> database object, but still uses the same odb::transaction, since, inside my >> framework, when it sees that a thread_local odb::transaction is already >> loaded it doesn't try to open a new transaction, but still creates a new >> odb::database.. >> >> It's possible that both of those were mishandling of the library on my >> side that were never checked, but they have been working flawlessly for 2 >> years so now I am left scratching my head about what would be a correct >> path of dealing with it. >> >> On Tue, Feb 18, 2025 at 12:37?PM Boris Kolpackov >> wrote: >> >>> NIkolai Marchenko writes: >>> >>> > I am getting this error: >>> > >>> > >>> /home/zeks/odbbuild/libodb-gcc-9/libodb-gcc-9/libodb-2.5.0/odb/transaction.cxx:340: >>> > virtual odb::connection& >>> > >>> odb::transaction_impl::connection(odb::transaction_impl::database_type*): >>> > Assertion `db == 0 || db == &database_' failed. >>> >>> This is a "sanity check" that makes sure you don't use a transaction that >>> was started on a different database instance. This check is actually new >>> in 2.5.0, I see it's not present in 2.4.0. So maybe it is catching an >>> error on your side? >>> >>> The only significant threading-related change in ODB 2.5.0 is that we >>> have switched to C++11 threads. In ODB 2.4.0 we used POSIX threads on >>> POSIX and Win32 threads on Windows. But I don't think this should matter, >>> even if you are using the POSIX API for TLS. >>> >>> >>> > This happens modestly in thread workers, my code is keeping >>> thread_local >>> > instance of odb::transaction obtained with db->begin(). >>> >>> It would be interesting to see if database_ points to a valid database >>> instance. >>> >> From boris at codesynthesis.com Wed Feb 19 08:33:37 2025 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Feb 19 08:32:17 2025 Subject: [odb-users] any significant changes to threading model in 2.5? In-Reply-To: References: Message-ID: NIkolai Marchenko writes: > Correct me if I am wrong: I was of the opinion that generating a new > database object didn't do anything to an internal thread_local connection > held by an odb::transaction instance. The check was added to detect the following type of errors (using SQLite database files for illustration): database db1 ("db1.sqlite3"); database db2 ("db2.sqlite3"); transaction t (db1.begin ()); db2.load (); In 2.4 the above code would silently try to load the object from db1. > 1) Loading an internal lazy object in a separate thread via .load() > compared to where the original outside lazy object was acquired I am not sure what you mean by "lazy objects". All ODB lazy mechanisms (lazy pointers, lazy-loaded object sections) either embed the database instance (lazy pointer) or expect you to pass the database explicitly (sections). I don't believe we have any cases where you call load() and it just uses whatever the current transaction might be. > 2) Trying to persist an object in an odbcallbackhook that creates a new > database object, but still uses the same odb::transaction, since, inside my > framework, when it sees that a thread_local odb::transaction is already > loaded it doesn't try to open a new transaction, but still creates a new > odb::database.. Yes, this feels wrong. Conceptually, in ODB, a transaction belongs to a connection and a connection belongs to a database. It seems in your framework all instances of odb::database "point" to the same underlying database and thus it doesn't matter "whose" transaction/connection you are using. But this assumption does not hold generally.