[DBO] Information regarding what action is performed in 'persist' method.

Added by Plug Gulp over 1 year ago

Dear Wt Team,

Is there a way to get information about what type of action is being
in the persist method?

This will be useful for, say, if a 'created_date_time' and 'updated_date_time' fields of a table needs to be set. When a row entry is created then current date-time can be set to the 'created_date_time' field in the persist method; and when data of a row is updated then the 'updated_date_time' field is set to current date-time.

This facility to detect what type of action is being performed in the persist method will also help in creating audit trail.

Is there a way to detect the type of action being performed in the persist method? Or is there a simple workaround to achieve this?

Thanks and kind regards,


Replies (1)

RE: [DBO] Information regarding what action is performed in 'persist' method. - Added by Roel Standaert over 1 year ago

The actions themselves don't really expose an interface that makes clear which action is being executed precisely, except for the getsValue(), setsValue(), and isSchema() functions.

  • getsValue() is true for an action that gets the value from the object (e.g. SaveDbAction, but also e.g. JsonSerializer)
  • setsValue() is true for an action that sets the value in the object (e.g. LoadDbAction)
  • isSchema() is true for an action that creates or drops the schema (i.e. InitSchema and DropSchema)

getsValue() and setsValue() can e.g. be used to create a Dbo class with getters and setters instead of direct member access, or to add read-only members.

Of course, since the Action is a type template parameter, you can access compile-time information about it (e.g. through typeid(Action).name()), and check its type, which can be combined with isTransient() (since SaveDbAction is used both for INSERT and UPDATE):

class A final : public Wt::Dbo::Dbo<A> {
  template<typename Action>
  void persist(Action& a) {
    // Only run this code if the action is a SaveDbAction
    if constexpr (std::is_same_v<Action, Wt::Dbo::SaveDbAction<A>>) {
      // We can check isTransient(), or alternatively check if the created timestamp is set
      if (self().isTransient()) {
        // Object was not persisted yet, update created timestamp
      // Update updated timestamp

Note: SaveDbAction calls persist 2 to 3 times, and the exact action definitions are part of an internal, undocumented API, so this is a bit hacky, but it's the best I could immediately think of.

Of course, we most often set the created timestamp upon construction, even though this isn't exactly when the object gets persisted.

As another alternative, you can use triggers if your database supports them. Of course, the updated value won't be reflected in the object until you reload it from the database.