thojanssens1

thojanssens1

This will work:

Repo.insert!(
  %Vote{
    user_id: user_id,
    input_id: hd(input_ids)
  },
  prefix: Triplex.to_prefix(tenant)
)

Query generated:

INSERT INTO “localhost”.“votes” (“input_id”,“user_id”,“id”,“inserted_at”,“updated_at”) VALUES ($1,$2,$3,$4,$5)

This won’t:

new_votes =
 [
   %{
     input_id: "2c92c315-b81f-413e-8014-b7a0ab2038a6",
     user_id: "2dd65dcd-9741-4075-943c-c372c8a2ae97"
   }
 ]

Ecto.Multi.new()
|> Ecto.Multi.delete_all(:delete_votes, delete_votes_query, prefix: Triplex.to_prefix(tenant))
|> Ecto.Multi.insert_all(:insert_all, Vote, new_votes, prefix: Triplex.to_prefix(tenant))
|> Repo.transaction()

Error:

** (Postgrex.Error) ERROR 23502 (not_null_violation) null value in column “id” violates not-null constraint
table: votes
column: id

Query generated:

INSERT INTO “localhost”.“votes” (“input_id”,“user_id”) VALUES ($1,$2)

I do not understand why Ecto.Multi.insert_all doesn’t generate id and timestamp columns like Repo.insert! does.

In the Vote schema we have:
@primary_key {:id, Ecto.UUID, autogenerate: true}

deps: {:ecto_sql, "~> 3.1"}

Any help?:frowning:

Showing Posts 1 to 10

al2o3cr

al2o3cr

I do not understand why Ecto.Multi.insert_all doesn’t generate id and timestamp columns like Repo.insert! does.

The ID thing is definitely weird, but the timestamps not being generated is documented behavior:

If the schema contains an autogenerated ID field, it will be handled either at the adapter or the storage layer. However any other autogenerated value, like timestamps, won’t be autogenerated when using insert_all/3.

There’s this thread that describes almost exactly the same issue, but what needed to change to make the problem go away isn’t clear :frowning:

fuelen

fuelen

IDs generation can be moved to the database level. Postgres has great uuid-ossp extension. Enable it, set the default value for id column to uuid_generate_v4() and use @primary_key {:id, Ecto.UUID, read_after_writes: true}.

thojanssens1

thojanssens1 OP

See docs in link below mentioning that UUID are actually purposely not autogenerated:

https://github.com/elixir-ecto/ecto/commit/99dff4c4403c258ea939fe9bdfb4e339baf05e13

LostKobrakai

LostKobrakai

The *_all functions in ecto deal with queries and plain values, but not schemas. Even if you supply a schema module, it’s only used for building an query (they’re Ecto.Queryable’s).

Given all the timestamp and autogenerate stuff is defined for schemas, those functions don’t know about those things and therefore can’t handle them.

thojanssens1

thojanssens1 OP

Thank you. But then I still wonder what’s the reason that we don’t have a version of those *_all functions that “do more”/“are smarter” (e.g. autogenerate an UUID), in addition to the lower-level ones (allowing then to avoid using insert in an Enum.each if you want to use Schema’s configs).

Also why are specifically the *_all functions lower-level at all, as opposed to other functions? I don’t grasp the design choices.

LostKobrakai

LostKobrakai

Likely because they can’t do everything. Repo.insert can deal with assocs, which requires it to run multiple queries. All the *_all functions run just a single sql query, so they cannot support associations at all. So instead of opting for the vague middleground of supporting some schema based features and not others they simply support non of them. This is besides the fact that those functions are meant to work without needing schemas in the first place.

thojanssens1

thojanssens1 OP

It’s still hard for me to see why we can’t take into account the auto generated fields if an Ecto schema is passed as first argument. This is not related to associations. If I change my timestamp from naivedatetime to datetime, now I have to change the code using insert_all and such functions, or (less likely) if I change the type of id.

I can live with it though.

LostKobrakai

LostKobrakai

The “IF an Ecto Schema is passed…” is exactly why.

Supporting only a subset of schema based functionality of only a subset of possible arguments to *_all functions will be even more confusing than just saying: sorry all the schema stuff is not supported here. Besides the fact the implementation of the latter is likely way simpler to maintain.

Basically *_all functions are build to support Repo.insert_all("table", [%{id: 1}]) – maybe even more than Repo.insert_all(MySchema, [%{id: 1}]). Repo.insert is the other way round. It supports only schemas, but not plain queries.

thojanssens1

thojanssens1 OP

Could we mention one concrete example of a schema functionality (among the whole set of schema functionalities) that would be confusing for not to be supported in the case that support for field generation (id/timestamps) is added?

LostKobrakai

LostKobrakai

With fields on schemas you can alter the column name of a field:

schema "table" do
  field :test, source: "old_legacy_name"
end

Repo.insert_all(MySchema, [%{test: "value 1", old_legacy_name: "value 2"}]

What would this do under the assumption the function would work with schema functionality?

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
ryanwinchester
apply_graft/2 doesn’t rewrite an add_many sub-workflow’s deps on an add step. Grafted jobs cancel with “upstream job was deleted” Version...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews