Type-safe database access for Rust
APACHE-2.0 License
Bot releases are visible (Hide)
All current and future versions of OpenSSL 3 are now supported
Scalar list fields annotated with @unique
should work as filters for find_unique
and the like now.
Published by Brendonovich 11 months ago
Perhaps the biggest update yet to Prisma Client Rust is here - version 0.6.0! Plenty of new features, new integrations, official Prisma sponsorship thanks to the Prisma FOSS Fund, new docs, a Discord server, and enough functionality to make Prisma Client Rust (in my opinion) better than Diesel, SeaORM and SQLx - especially for web development!
Now, lets check out 0.6.0's breaking changes:
create
Previously, it was necessary to wrap required arguments in create
calls in a call to set
or link
to identify which field was being targeted, but this was redundant - each argument already corresponds to a specific field.
For this reason it is no longer necessary to include set
or link
calls for required fields.
This change pairs well with having inlay hints enabled in your editor, as VSCode/neovim/whatever you're using can remind you which argument corresponds to which field, rather than having to type it in code.
Here's some stripped down examples of what this change looks like:
create(user::name::set("Brendan".to_string()), vec![])
-> create("Brendan".to_string(), vec![])
create(user::profile::link(profile::id::equals(0)), vec![])
-> create(profile::id::equals(0), vec![])
update_*
and delete_*
are now dedicated actionsupdate_*
and delete_*
being created from find
queries was a behaviour inherited from Prisma Client Go, and now they are dedicated actions.
find_unique(where).update(data)
-> update(where, data)
find_many(where).update(data)
-> update_many(where, data)
find_unique(where).delete()
-> delete(where)
find_many(where).delete()
-> delete_many(where)
link
and unlink
renamedlink
and unlink
have been renamed to connect
and disconnect
in an effort to keep consistency with Prisma Client JS.
Cursor
types removedIt turns out that the specifier needed for the cursor
field function can just be a UniqueWhereParam
, so field::equals()
can be used as a drop-in replacement to field::cursor()
.
Previously, all JSON values fetched from a database would be converted to a serde_json::Value::String
, rather than their correct serde_json::Value
representation.
QueryError
prisma_client_rust::queries::Error
has been renamed to QueryError
, and is now accessible as prisma_client_rust::QueryError
.
The error_is_type
function has been removed in favour of QueryError::is_prisma_error(&self)
, which can be called with a generic UserFacingError
in the same way as error_is_type
.
update
and delete
no longer return an Option
While Prisma Client JS returns Data | null
for find_first/unique
, it does not do so for update
and delete
, so Prisma Client Rust will do the same.
In my opinion this makes more sense, as finding data comes with a decent expectation that a record may not exist. For mutations though, you're attempting to target a specific record and failing to do so should be an error.
RelationNotFetchedError
As requested in #118, relation accessor errors are no longer just strings, but have a dedicated error type that is compatible with anyhow
and thiserror
.
The version of quaint
(a Prisma crate) being used now has platform-specific features for some of its dependencies. This requires using version 2 of Cargo's feature resolver. In non-workspace projects, this can be done by setting edition = "2021"
in the Cargo.toml
. In workspace projects, this can be done by setting resolver = "2"
in the root Cargo.toml
. More info is available in the installation documentation.
If I've missed any breaking changes please let me know, I'm still getting used to this open source maintainer thing!
Now, on to the fun new stuff:
select
and include
The feature I'm most excited about is the new select
and include
macros & query builder functions.
Fully type-safe relation fetching & the ability to select exactly the fields you would like to fetch from a model.
You can read all about it in the docs, but here's a small example:
// Type inside Vec is anonymous and does not exist outside of the call to `include`
let posts: Vec<_> = client
.post()
.find_many(vec![])
.include(post::include!({ // Every model gets select & include macros
comments: select { // Nested select/include is supported
id // Only select the exact fields you need!
}
}))
.exec()
.await?;
// Macro output type is equivalent to
struct Data {
id: String,
title: String,
comments: comments::Data
}
mod comments {
pub struct Data {
id: String
}
}
While with
/fetch
works well and has excellent autocomplete support, determining whether a relation has been fetched is left to runtime checks, rather than being enforced by data types. If you're fine with doing runtime checks then with
/fetch
will serve you well, but if you need to select specific fields then you'll have to use the select!
macro.
Going forward, I will try to bring as many relation-fetching features to both with
/fetch
and select
/include
, but some may simply require the magic of macros.
count
queryRetrieving the number of records that match some filters is now super easy. Check the docs for an example!
create_many
queryFor all databases except SQLite, create_many
is now available and can be read about here.
For those of you using SQLite, create_many
support can be enabled by adding the sqlite-create-many
feature to both prisma-client-rust
and prisma-client-rust-cli
. Please keep in mind that this feature is EXPERIMENTAL and is not supported or tested by Prisma, but we've been using it at Spacedrive and it's worked pretty well.
PrismaClient::_batch
is now available for running a sequence of queries inside a transaction! It's fully type-safe and works with tuples and iterators, as explained here
rspc
integrationEnabling the rspc
feature for both prisma-client-rust
and prisma-client-rust-cli
makes it possible for the rspc
router to generate TypeScript bindings to your Prisma types by simply returning the result of a query inside a resolver. Errors can also be handled, and it's all explained here.
Different filters that apply to the same field are now merged properly, so case sensitive comparisons should now work.
An internal use warning is no longer printed when running the CLI with no arguments, instead the CLI's help menu is printed.
While Prisma v4.3.0 just got released, I wanted to get this release out ASAP so 4.3.0 features may be supported sometime in the future.
In an effort to make the generator of the CLI more approachable, significant refactoring has been done to make it more modular and understandable.
Turns out that previously, cloning Brendonovich/prisma-engines would clone every branch in the repo, resulting in a 400mb download. After deleting every branch except main
I screwed something up resulting in 0.5.3 needing to be released, but now downloading the engines is only a 40mb endeavour!
It's been requested in the past and I felt that Discussions would be adequate, but now I would rather help and discussion be done in Discord - it's much easier to interact one-on-one and ask questions about feature ideas that way.
However, I don't feel that Prisma Client Rust is a big enough project to warrant having its own server, so it will share one with rspc
. The two projects pair together extremely well, I expect many of you using Prisma Client Rust will use rspc
, and the developer of rspc
is a friend and coworker. We are both very familiar with each other's technologies and can be more helpful in one place.
To my amazement, Prisma chose Prisma Client Rust as the July recipient of their FOSS fund! This money is greatly appreciated and will aid future development of Prisma Client Rust.
There's plenty more that can be added to Prisma Client Rust, but I hope that 0.6.0 will offer enough features that more updates can wait for some time, and that community members can start contributing rather than me implementing things.
Optimisation is something I'd like to pay extra attention to - only including required database connectors, reimplementing generic engine functions to be database-specific, benchmarking comparisons to other Rust ORMs, and more. Compile times are currently abysmal, I'd like to see that change.
Thank you everyone for all the support Prisma Client Rust has been getting, it's incredible that something I whipped up for work has turned into officially-supported and legitimate open source project. Heres to more features, more users, and becoming the best ORM in the Rust ecosystem 🎉
Published by Brendonovich about 1 year ago
The default_generators
feature is now enabled in the engines when using MongoDB, so using auto()
in a schema should work properly.
Published by Brendonovich about 1 year ago
Systems running OpenSSL 3.1.x will now download the OpenSSL 3.0.x versions of the Prisma engines.
Argument numbering now goes from 1 -> N rather than 0 -> N-1.
Published by Brendonovich over 1 year ago
It is now recommended to put #[allow(warnings, unused)]
wherever you declare your generated client's mod ...;
, as this allows the client to be imported via import!()
.
QueryError
now implements Serialize
(#305)partial_unchecked
fields now pub
(#311)Published by Brendonovich over 1 year ago
Big release today for MongoDB users, with support for composite fields and raw mongo queries! partial!
is also here, along with a bunch of bug fixes.
It is now possible to perform CRUD operations with MongoDB's embedded documents, with type- and field-level modules now generated with similar types as regular models.
_run_command_raw
, find_raw
, and aggregate_raw
are all now available when using MongoDB.
The partial_unchecked!
macro is now available for all models, providing an easy way to convert input objects to update_unchecked
parameters.
create_unchecked
, update_unchecked
, UncheckedSetParam
For cases where yo want to interact with foreign keys, create_unchecked
and update_unchecked
allow you to do so without risking a runtime error by including a relation operation, improving type-safety. In a future update foreign key operations will be removed from SetParam
enums.
.env
file loadingdotenv
is now being used instead of std::env
, so the client can read from .env
files at runtime.
Unsupported
field handlingModels that have Unsupported
fields won't throw errors, instead it will not be possible to create records of them if the field is required. The fields will also not be returned from queries. Thanks to @laptou for helping with this!
specta
featurePCR can now be used with Specta independently of rspc
Next up on the agenda is a bunch of breaking changes like #300, #83, and big changes like #263 and #44, but those will come later.
Published by Brendonovich over 1 year ago
Just a few bug fixes this time, nothing major.
Prisma recently updated their fork of mysql_async
, the crate which powers the engines' MySQL support, with a breaking change. Due to how Prisma lock git dependencies to branches rather than commits, this breaking change was propagated through quaint
, the engines, and all the way to PCR. For now I have locked mysql_async
to a specific commit on my fork of quaint
, but Prisma are aware of this issue and are working to remove git dependencies.
0.6.4 had a regression where read filters like is_empty
were not generated for scalar list fields.
Reserved keyword transformations are now applied after doing case conversions of model and field names, so models names are now prepended with r#
if they would otherwise be a reserved keyword.
Hopefully the next update can be 0.7.0, it just won't be for a while. In the meantime I'd like to gauge sentiment for turning select
and include
into proc macros (#250) - would you all be opposed? I think it would break autocompletion inside the macros (not sure how big a concern that is seeing as existing autocomplete only works one layer deep), but would allow for much better error handling and reporting, and cleaner code in the generator. If you've got thoughts on this please join our Discord and let me know!
Big thanks to my sponsors @m1guelpf and @DominoTree!
Published by Brendonovich almost 2 years ago
What was going to be a small release with some bug fixes has turned into a whole lot of features and changes, but 0.6.4 is finally here!
First, I'd like to thank @0xtlt and @Congyuwang for their generous sponsorship. It really means a lot to me!
Any combination of tuples and Vec
s can now be batched together
With Prisma bringing interactive transactions into GA in 4.7.0, they've now been implemented with both closure-based and begin/commit/rollback
methods being supported.
Sometimes you may want to write tests that don't connect to a database. Mocking is great for this, allowing you to create a client that retrieves query results from values you pass in beforehand.
A whole lot of traits have been added and implemented for the query builders. These can be used to make reusable wrapper functions that can add parameters to multiple types of queries in a generic manner.
is_null
field function (#214)This field function is available for checking if optional 1-1 relations are connected or not.
When using specta/rspc, dedicated TypeScript types will be generated for named select
and include
types. Though this is possible, it's recommended to use rspc.inferProcedureResult
and the like to extract procedure types.
A regression in 0.6.3 messed up how enums are qualified in the codegen. This is now fixed, along with some QoL improvements.
not
field function now Option
for optional fields (#206)FindMany
batch type (#208)Upsert::include
accepts IncludeType
(#221)r#
(#194)I probably won't put out another release until 0.7.0. This library is at a pretty good point right now feature-wise, and I'd like to focus on improving documentation and creating content to increase awareness.
Again, thank you to my sponsors, and thank you to everyone who has created issues, tested changes, submitted PRs, joined the Discord, and starred the repo!
Published by Brendonovich almost 2 years ago
It's time for another update, this time with some bug fixes, cleaner errors and a new builder API for PrismaClient
!
While new_client
and new_client_with_url
will remain supported for now, PrismaClient::_builder
will be the recommended approach from now on. It is cleaner and more extensible, and will be the only solution when 0.7.0 is released.
Previously, any errors that occurred while generating the client would result in an ugly JSON blob being printed to the console. This is because the generator would just panic when it should have sent an error response back to the CLI.
Errors are now sent to the CLI properly, making them more clearer and readable. I can't promise that they will all be this way, but it's definitely an improvement.
skip_duplicates
is no longer generated for databases that don't support it - #173--schema
are now respected - #183count
passes through where args - #177and!
merges operators applied to the same field - #175order_by
params are treated as an array - #176WhereParams
used to contain every possible combination of filters and fields, which made them very long and resulted in a lot of duplicate code. Now, filters are generated for each field type - be that String, Int or something else - and reused in all other WhereParams
. This shouldn't affect any code you write, it just makes internal stuff nicer.
sdk/example
contains an example of a custom generator could be built. It's just an example for @oscartbeaumont at the moment, and I don't endorse building custom generators yet, but will be supported in future.
The mutation-callbacks
feature allows callbacks to be registered on the client builder that are triggered when a mutation is ran (eg. create, update, delete). This is purely for use at Spacedrive and is not recommended for public use.
Many thanks to @Congyuwang and @affanshahid for contributing to this release!
Published by Brendonovich about 2 years ago
A new release is here with more features, bug fixes, and faster compile times!
Thanks to collaboration with @oscartbeaumont It is now possible to use Prisma's migration engine to apply schema changes and migrations! I don't recommend using this in all projects (if you can migrate with the CLI then do so), but for applications like those built with Tauri this is a great solution for applying migrations on users' machines. Please note that using this feature will likely cause your generated client to be non-transferrable across devices and operating systems, so it will have to be generated separately anywhere you want to use it and be removed from source control if you have it checked in.
Enable the migrations
feature for the library and CLI and read the docs for more info. Thanks to @oscartbeaumont for helping get this done.
The default behaviour of Prisma Client Rust is to compile and include all database connectors. This adds anywhere from 10-30% more compile time depending on which specific connectors you actually need.
0.6.2 makes it possible to disable support for all connectors using default-features = false
, and then selectively re-enable them with connector-specific features. postgresql
, mysql
, sqlite
, mssql
and mongodb
are all valid options.
Make the mentioned changes for the library and CLI and you should notice compilation improvements immediately!
create_unchecked
0.6.1 acknowledged that create_many
can only accept scalar fields, but wrongly changed create
to do the same, making it incompatible with upsert
. Now create_unchecked
is the helper to be used with create_many
, and create
can be used with upsert
.
rspc
0.1.2 SupportRecent changes to rspc
have made 0.6.1 incompatible with newer releases, so the minimum version of rspc
has been bumped to 0.1.2.
On the subject of rspc
, enums are usable in resolver return types!
These changes have been a long time coming but I wanted to test them as much as possible, especially the migrations feature. How best to take advantage of it is still up in the air, but create-rspc-app
from @oscartbeaumont and @VarunPotti should help with that in the near future. It will be a CLI for initializing a new project with any combination of Prisma, rspc
, axum
, Tauri and a website that takes incorporates a lot of the patterns we adopted building Spacedrive.
The next things I would like to see happen with Prisma Client Rust is a simplification of the codebase, especially the generators, such that external contributions and custom generators get easier; Use of more traits such that query builders can be modified generically and be constructed from JSON; More tests, preferably a setup that has general tests that run on all supported DBs and specific tests for certain DBs; Better docs are also a must, and if anyone would like to help write some I would be very grateful!
Published by Brendonovich about 2 years ago
Got a small release here with some improvements to create_many
and a change to how types are exported when using rspc.
create_many
only accepts scalar fieldsWhen implementing create_many
I made the mistake of using the same argument structure of create
and put it in a Vec
.
This is not correct as create_many
does not permit using relation fields with connect
, instead it only allows setting scalar fields of the model. Models' create
utility and create_many
have been changed to reflect this fix.
This is a breaking change, but any create_many
involving a relation would always result in an error, so I don't feel a new minor version is warranted.
create_many
has skip_duplicates
functionPrisma Client JS has a skipDuplicates option, which was not implemented in 0.6.0. Now it is possible to call skip_duplicates
after create_many
, providing the same functionality as the JS option.
Previously, model types exported via rspc exactly mirrored model Data
structs, containing all scalar fields as well as optional relation fields.
After integrating this and replacing uses of with/fetch
with include
in Spacedrive, I have decided to encourage utilising the extra type safety provided by include
and removed all relation fields from model types, so that they only contain a model's scalar fields.
More information can be found in the docs.
Published by Brendonovich about 2 years ago
This release fixes a recently introduced issue (sorry, my bad!) regarding version resolution of the Prisma engines. It seems that in preparing for 0.6.0 I broke 0.5.2 🙃.
I'm aiming to release 0.6.0 by the end of the month. With it will be many new features, some bug fixes, and Prisma v4.2.0.
Published by Brendonovich over 2 years ago
Prisma Client Rust is here with some important bug fixes, extra features, and preparation for 0.6.0.
Bytes
type now supportedInteracting with a field that had the Bytes
type would result in an error. This is because Prisma was taking the Vec<u8>
of data and base64 encoding it into a string, but Prisma Client Rust expected a Vec<u8>
, leading to a deserialisation error. This is no longer the case, as I have made a clone of the PrismaValue
enum that does not base64 encode bytes when serialised.
Vec
(#80)Some simple errors in the codegen were resulting in cursor variants of scalar arrays not expecting Vec
s.
A simple negation error was leading to link/unlink being generated on the wrong fields.
self
Calling create
, find_unique
etc. now consumes the Actions
instance that is created when calling a client's model accessor. This means that doing let query = client.model().create();
no longer produces an error, since the Create
struct doesn't reference the Actions
struct it was created from.
Calling upsert
will now always provide the Prisma engines with arguments for create
and update
, even if an empty array is provided. This is required according to the engines GraphQL schema.
Clone
This is more of a change for myself than anything.
sdk
crateWhile not ready for public use yet, the sdk
crate will be the new home of much of the generator logic in order to make building custom generators much easier. I am doing this now as we are using it at Spacedrive, but it is not ready to be used publicly. It will change.
Published by Brendonovich over 2 years ago
Prisma Client Rust 0.5.1 is here with some minor bugfixes!
@id
and @unique
do not duplicate UniqueWhereParam
#71 has been fixed, so annotating a field with @id
and @unique
together will not result in two variants being generated inside a model's UniqueWhereParam
enum.
UniqueWhereParam
variants#69 detailed a regression in which compound IDs do not generate a corresponding UniqueWhereParam
variant. This was a result of using more of Prisma's internal schema types, in which primary keys are stored separately to unique fields, and as such unique variants were not being generated for compound IDs.
Published by Brendonovich over 2 years ago
It's been a while and some big changes have been made, but Prisma Client Rust 0.5.0 is here! Improvements include major internal optimisations, Arm64 and Prisma 3.13.0 support, many bugfixes and more!
Prisma CLI binaries have been published for Arm platforms, and now Prisma Client Rust can download different CLI binaries depending on your CPU architecture. These binaries seem to be stable, but have not been extensively tested, so please report any issues you find.
Codegen now relies heavily on Prisma's internal datataypes, resulting in more accurate and reliable generated code. The generated client also uses PrismaValue
s extensively, providing a more accurate interface with the Prisma engines.
Prisma errors can be annoying to handle, so documentation and the function error_is_type
have been added to improve the experience of determining whether an error is of a particular type.
By checking against the list of Rust's reserved keywords, the CLI will now let you know if any of your model or field names match any reserved keywords, instead of simply failing to compile after generating the client.
PrismaClient
, internal enums and more are now generated inside the _prisma
module, rather than at the root of the client. This ensures that enums, which are generated at the root, never have naming collisions with internal types.
upsert
now takes 3 parameter: A unique filter, the create args, and update args all in one, as opposed to create
and update
having to be called separately. This has been done in order to be more type-safe, since not calling create
or update
previously would have resulted in an error from Prisma.
Debug
by simply outputting "PrismaClient"
WithParam
sI have recently joined the team at Spacedrive and will be focusing most of my work on Prisma Client Rust towards features that are required there, but will also try and do extra during my time off. I endeavour to complete #60 and #24 for 0.5.1/0.6, but not much more than that for now. I will, however, be working on improving the experience of creating custom generators, as these will be required at Spacedrive, and my friend @oscartbeaumont is developing a GraphQL library that will use a custom Prisma generator for an incredible Rust, Prisma and GraphQL experience.
Thankyou to everyone who has starred, shared and opened issues on this project. It's been a blast working on a library that people are excited about, and I look forward to seeing Prisma become more widely used in the Rust community!
Published by Brendonovich over 2 years ago
In the pursuit of closing #45, I also ended up closing #22. So here's a minor update with some major features and performance boosts!
It would be greatly appreciated if you starred and shared this repo!
fetch
now has all the same methods on it as find_many
and find_unique
, meaning you can fetch relations to an infinite depth, and even paginate relations at the same time!
The re-implementation of the query AST has made it possible to convert directly from enums and structs to GraphQL structures, bypassing an entire step before execution where a GraphQL string was constructed and then parsed.
Thanks to @aaronleopold for creating an example of using Prisma Client Rust with async-graphql
and axum
!
Published by Brendonovich over 2 years ago
After much work, I'm excited to release version 0.4.0 of Prisma Client Rust! 🎉
This release is much more refined than the initial versions, with many bugs fixed, many approaches rethought, and a whole load of breaking changes 🙃 (trust me, it's for the best). All the information you should need is available in the docs, and if you have a question then feel free to ask!
It would be hugely appreciated if you starred and shared this repo!
To allow tying the CLI version to the specific project it is being used in, the CLI is now available as a library and can be used to create a custom executable within your project. Additionally, none of Prisma Client Rust's code will be distributed on crates.io going forward, as 1. There are plans to use Prisma engine code in the CLI and 2. it's more consistent.
All the functions, structs and enums related to models and fields are now inside their own modules. This was done to standardised naming within the code generation and have consistency between model and field accessor naming (since models used to be PascalCase while fields were snake_case).
update
and upsert
queries are now supported.
Result
valuesAn await
ed query will return a Result, with the error type being a prisma_client_rust::query::Error
Many filters are now discovered through the Prisma engines, so more expressive queries can now be made.
take
, skip
, cursor
and order_by
filters are all available too!
Separate types now exist for unique fields, narrowing the values that can be used in find_unique
queries.
Equality comparisons of compound unique fields can be constructed with ease.
Previously, engine binaries did not download properly on Linux. This is fixed now thanks to collaboration with @oscartbeaumont.
Optional single relations are now stored as Option<Option<Data>>
on data structs, and thus whether they have been fetched or not can be reported as an error.
Published by Brendonovich over 2 years ago
As detailed below, the method for installing both the CLI and the library have changed, so it is recommended that you check the updated README for instructions on how to properly install them both.