dwyl / alog

🌲 alog (Append-only Log) is an easy way to start using the Lambda/Kappa architecture in your Elixir/Phoenix Apps while still using PostgreSQL (with Ecto).
GNU General Public License v2.0
15 stars 2 forks source link

Update - Ecto.Adapters.SQL.Connection #46

Open Danwhy opened 5 years ago

Danwhy commented 5 years ago

part of #38

https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.Connection.html#c:update/5

Our update implementation needs to work in much the same way as our insert, but it also needs to compare the newly generated cid to the old one, and not do anything if they are the same as it means the data is unchanged. If they are different, it needs to be added to the row as the previous_cid.

RobStallion commented 5 years ago

Are we planning on turning the entire map/struct into a cid? If so how do we plan on comparing the new cid to the old one? Each CID should always be unique as the struct passed in will contain timestamps.

Could we compare the new params to the old params instead?

Danwhy commented 5 years ago

It depends on when we actually create the cid I guess. When do the timestamps actually get added? I would think it's not until the item is actually inserted into the database, at which point the cid would already exist

Danwhy commented 5 years ago

Re: @RobStallion's comment above. It turns out that Ecto already compares the parameters in the changeset function, and only passes through those that have changed to the Adapter's update function. If none of them have changed, the function doesn't get called, so we actually have no need to compare the cids before updating.

Danwhy commented 5 years ago

Some of the issues I've encountered so far:

If passing a schema to the update function, an error will be thrown if the schema does not have a primary key. This means we have to require users to define the cid primary key in their schema. Not ideal, but we can write a macro to help: see https://hexdocs.pm/ecto/Ecto.Schema.html#module-schema-attributes for an example

To allow for the cid to be generated on the backend, we need to pass autogenerate: true when we define it. Autogenerated ids cannot have a primitive type such as :string. I'm able to insert a binary as the id value, but I get an error when I try to call the update function:

** (Ecto.ChangeError) value `"zb2rhn1C6ZDoX6rd"` for `Alog.TestApp.User.cid` in `update` does not match type :binary_id

Looks like we may need to define the loaders functions: https://hexdocs.pm/ecto/Ecto.Adapter.html#c:loaders/2

Danwhy commented 5 years ago

I've managed to get this function fully working, it creates a new row in the database with the updated fields and a new cid.

The only issue is the return value of the update function. The returned struct seems to be built separately from what is actually inserted into the database, and it's not being built correctly; the cid remains the old value, while the updated fields are updated. I need to take a look at how the struct is returned and see what we can do.