sqlx-batch
Procedural macro for ergonomic insertion of vecs of structs into a PostgreSQL database.
Why this macro?
Bulk inserts in sqlx can be quite cumbersome to write manually. Consider the case where we have some vector of structs:
SomeStruct
let to_insert = vec!;
If we want to insert this vec of structs into a Postgres database we would first have to collect the struct fields into three individual vectors and manually write the UNNEST query.
The macro
Instead, we can use sqlx-batch to write this for us. Consider the same struct. When annotated as follows:
use BatchInserter;
It expands to the following struct definition with functions which help us do this transformation easily:
Note that the name of the generated struct will always be {ANNOTATED_STRUCT}Inserter. So SomeStruct becomes SomeStructInserter.
We can then create the sqlx query by calling:
from.build
Upserting
You can also annotate certain fields with the #[key] attribute to specify that you want to do an upsert where these (one or more) fields specify the primary key or uniqueness constraint. The following:
Will generate the following SQL in the resulting sqlx query after calling build():
INSERT INTO "keyed_test_table" (elem_1,elem_2,"renamed_elem_3") SELECT * FROM UNNEST ($1::integer[],$2::text[],$3::bool[])
ON CONFLICT ("renamed_elem_3") DO UPDATE
SET elem_1=excluded.elem_1,elem_2=excluded.elem_2
Limitations
The mapping of Rust types to Postgres types (needed for the types specified in the UNNEST clause) is far from exhaustive. Currently, the proc-macro will simply panic if it encounters a type which it does not know how to translate.