Ash Postgres: How to detect change when updating nullable column from NULL to non-NULL value without using atomic_update?

Hi,

I stumbled over this snippet of a query generated by an update action:

SET “updated_at” = (CASE WHEN $1::timestamp != r0.“last_query_at”::timestamp THEN $2::timestamp ELSE r0.“updated_at”::timestamp END)

The attribute is defined as below, i.e. the column is nullable:

attribute :last_query_at, :utc_datetime_usec do
  public? true
  filterable? true
end

When the record/row has NULL in field/column last_query_at and I pass a date-time value for last_query_at to the update action, the operator != prevents the condition to resolve to TRUE, hence updated_at is not changed although the row is changed to a new value for last_query_at (not shown in the snippet above).

That default behavior caught me by surprise.

From what I found so far, I‘d have to use this in the update action to skip the “only update if changed“ optimization:
change atomic_update(:last_query_at, expr(^arg(:last_query_at)))

Am I missing something to make the update of updated_at work without atomic_update?

I am using ash 3.19.3 and ash-postgres 2.6.32.

Update: Using atomic_update leads to the same snippet being generated.

My workaround is to explicitly change the attribute updated_at in the action:

change set_attribute(:updated_at, &DateTime.utc_now/0)

Definitely a problem. Can you share more about the action definition? Ideally sharing a reproduction and opening an issue containing that. I can fix :slight_smile:

Yes, I’ll create a ticket, but probably not until Friday or the weekend.

Hey @jan-mb-me thank you for the find! This is fixed in the latest main of ash and will be included in the next release.

:person_bowing:

2 Likes

Wow, that was quick! Thank you, @zachdaniel.

Can’t test main here at work but the fix looks exactly like what was missing:

Release is available: 3.23.0

2 Likes

I couldn’t upgrade past 3.22.2. Starting with 3.23.0 (also with 3.23.1) an embedded resource (the only one so far) doesn’t work anymore:

(Protocol.UndefinedError) protocol Jason.Encoder not implemented for Xyz.Recordings.TransferSettings (a struct), Jason.Encoder protocol must always be explicitly implemented.

I have to postpone further investigation until Tuesday.

In case it matters: I am not using ash_json_api.

Please also update ash_sql

Hello @zachdaniel, Upgrading to ash 3.23.0+ and also upgrading ash_sql worked and my workaround became obsolete.
Thank you very much!

1 Like