nyxcode / ormx Goto Github PK
View Code? Open in Web Editor NEWbringing orm-like features to sqlx
License: MIT License
bringing orm-like features to sqlx
License: MIT License
Hello i want to use ormx = "0.2.0" because I'm working with sql 0.4 and actix and I can't update still to 0.5.
I'm getting this error from macros...
error[E0432]: unresolved import syn::export
--> /Users/macbookpro/.cargo/registry/src/github.com-1ecc6299db9ec823/ormx-macros-0.1.8/src/backend/common/table.rs:3:10
|
3 | use syn::export::TokenStreamExt;
| ^^^^^^ could not find export
in syn
I'm using Rust 1.50
thanks for your help...
Hello,
I tried to install ormx to use with sqlx and sqlite, it didn't work, it looks like there might be some dependency issues? Failed on Windows and Linux:
$ cargo new ormx-test && cd ormx-test && cargo add ormx sqlx -F sqlx/sqlite -F ormx/sqlite
error: failed to select a version for the requirement `ahash = "^0.6.2"`
candidate versions found which didn't match: 0.8.6, 0.8.5, 0.8.4, ...
location searched: crates.io index
required by package `sqlx-core v0.5.1`
... which satisfies dependency `sqlx-core = "^0.5.1"` of package `sqlx v0.5.1`
... which satisfies dependency `sqlx = "^0.5"` of package `ormx v0.10.0`
... which satisfies dependency `ormx = "^0.10.0"` of package `ormx-test v0.1.0 (/home/max/git/ormx-test)`
perhaps a crate was updated and forgotten to be re-vendored?
Hello!
I started experimenting with this crate and so far, I love it!
There is one thing that I'm curious about though:
All methods on Table
take a db: impl Executor<...>
argument except for insert
that takes a db: &mut <Db as Database>::Connection
.
Is there any reason for that? I find it quite annoying to be able to simply pass my &PgPool
anywhere except for insert
where I need to &mut pool.acquire().await?
.
if Dynamic updates (which can't use Patch) are really a common usecase... - NyxCode
We can use one full update query to compile check, and small generated queries for modified fields.
We must have the struct of all Option
fields, with all by default None
and changed are Some
. Nullable fields are Option<Option<T>>
.
Possible use case:
let mut update = User::new_update();
update.name = Some("asdf".to_owned());
update.update(&db);
And this use case might be also possible, but not necessary:
let mut update = User::new_update();
update.set_name("asdf".to_owned());
update.update(&db);
Here we use setters to make the variable of Some<T>
. It needs to generate a lot of functions, which might be redundant? But it looks better.
Discussion of it took place in the Discord.
I have an "unmapped" (to DB, meaning table does not contain a corresponding column) property User.phones
in my struct:
use serde::{Deserialize, Serialize};
use ormx::Table;
#[derive(Serialize, Deserialize, Default, Debug, Clone, Table)]
#[ormx(table = "users", id = id, insertable)]
pub struct User {
#[ormx(default)]
pub id: i32,
pub username: String,
pub password: String,
#[ormx(default)]
pub phones: Vec<Phone>,
}
On compile it says: error returned from database: 1054 (42S22): Unknown column 'phones' in 'field list'
As we discussed in the Discord, it needs something like #[ormx(skip)]
.
Hey,
I've been thinking a lot about that stuff lately and I honestly think ormx is the perfect candidate to build on and iterate towards a full-fledged ORM.
The features I'd personally like to see are more or less the featureset of Sequelize, to be more accurate:
Number 3 would be pretty much just additional things to implement on Table
and would be the most trivial
Number 1 is a tough one, as we need to find a way to synchronize tables before sqlx compiles and checks our queries.
For instance on an empty database, a model would try to compile its queries, but the table doesn't exist yet so compilation would fail.
I'm currently experimenting here: https://github.com/OtaK/ormx/tree/otak/schema-sync
On my current project, our naming standards require our table names to be singular, which led to the following issue in the case of the user
table:
#[derive(Table)]
#[ormx(table = "user", id = id)]
struct User {
#[ormx(column = "id")]
id: Uuid,
email: String,
password_hash: String,
}
yields the following errors:
error: error returned from database: column "id" does not exist
--> server/src/user.rs:31:10
|
31 | #[derive(Table)]
| ^^^^^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` (in Nightly builds, run with -Z macro-backtrace for more info)
error: error returned from database: syntax error at or near "user"
--> server/src/user.rs:31:10
|
31 | #[derive(Table)]
| ^^^^^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` (in Nightly builds, run with -Z macro-backtrace for more info)
The message is not ideal but I managed to figure out that it is indeed the fact that user
is a reserved name and that it should be quoted.
My current workaround (I'm using Postgres) is the following #[ormx(table = "\"user\"", id = id)]
and it does work but I wonder if ormx
should not defensively quote identifiers by default.
I understand that it requires custom logic from different backends (MySQL requires backticks `user`
while Postgres requires double-quotes "user"
) so it is likely non-trivial to implement.
At the very least, maybe warning about that potential issue in documentation and recommending quoting identifiers in the derive macro attributes would be the way to go in the short-term.
Linking to the issue on Syn since a number of libraries are affected -> https://github.com/dtolnay/syn/issues/956.
Having trouble compiling after installing fresh, getting 2 issues from the syn change
use syn::export::TokenStreamExt;
^^^^^^ could not find `export` in `syn`
And
out.append_all(quote!(as #ty))
^^^^^^^^^^ method not found in `TokenStream2`
EDIT: to clarify both these are in ormx-macros 1.8
Hello! Loving the library, thank you so much!
The only thing I'm missing for my use case is batched inserts. I need to ingest millions of rows into a DB as quickly as possible, and non-batched inserts would be an issue. I know sqlx supports it, so I imagine it shouldn't be that difficult to implement. I could take a crack at it myself, if you're interested - although I am not very experienced with sqlx.
What do you think? Personally, it would mean I would never have to look at other ORMs again :)
Cheers, have a great day!
I have an existing database with a column named default
. The ormx::Table
macro does not escape it in the generated SQL, causing cargo sqlx prepare
to fail.
I reproduced it here: https://github.com/Kinrany/ormx-escape-default-repro
This seems to be a regression because it has been addressed in #1
Sorry for opening another issue :/
When I try add FromRow derive to my struct at the same time as Table from ormx I got:
error: proc-macro derive panicked
--> src/models/users/list.rs:38:41
|
38 | #[derive(Debug, Serialize, Deserialize, FromRow, ormx::Table, Clone, Eq, PartialEq)]
| ^^^^^^^
|
= help: message: called `Result::unwrap()` on an `Err` value: Error("expected literal")
And when I try add Encode I got:
error: expected literal
--> src/models/users/list.rs:39:1
|
39 | #[ormx(table = "users.list", id = id, insertable)]
Can sqlx and ormx coexist at the same time on the same struct?
Hey!
I've been trying to work with the get_many
getters lately and they're essentially useless IMO because:
=
test on it in the SQL queryMeaning that you will have to resort to manual SQL queries if you're doing something as trivial as looking multiple records by a batched id/unique key.
I suggest changing the query in get_many to use a IN()
statement instead of =
and accepting a slice of arguments instead of a single one as it would semantically work as well.
But of course, as it'd be a breaking change, I'm triggering a discussion here.
I can take care of the implementation.
I'm trying to use ormx and I can't even get the example to run. If I use the schema
create table users (
id serial4 primary key,
first_name varchar,
last_name varchar,
email varchar,
last_login timestamp
);
and just a simple cargo build
I get a bunch of errors.
error[E0308]: mismatched types
--> src/schema.rs:21:10
|
21 | #[derive(ormx::Table)]
| ^^^^^^^^^^^ expected `u32`, found `i32`
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> src/schema.rs:21:10
|
21 | #[derive(ormx::Table)]
| ^^^^^^^^^^^ expected struct `std::string::String`, found enum `Option`
|
= note: expected struct `std::string::String`
found enum `Option<std::string::String>`
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> src/schema.rs:21:10
|
21 | #[derive(ormx::Table)]
| ^^^^^^^^^^^ expected `i32`, found `u32`
|
= note: this error originates in the derive macro `ormx::Table` (in Nightly builds, run with -Z macro-backtrace for more info)
because these are type mismatches in the compiler, they're almost impossible to debug. I'm using the latest postgres.
I think it would be valuable to add a mechanism for partial updates to ormx
similar to what the AsChangeset
derive from diesel does.
There are however various possible solutions, the most straightforward one being to require all fields in Patch
structs to be wrapped in an Option:
None
would not perform the update for the fieldSome(None)
would set a nullable field to NULL
Some(Some(val))
would set a nullable field to val
Some(val)
would set a non-nullable field to val
I started discussing this on the discord and @NyxCode kindly responded with interesting alternative ideas that I think are very much worth exploring. I'm quoting their message here to help start the discussion:
yeah so I did think about this a bit in the past.
I found that in most cases, it's most comfortable to avoid having to deal with nested Options and stuff like you would have to with diesel. That's also what I needed the most at the time.
I do think supporting this would be great though! Would having an attribute like#[ormx(ignore_if_none)]
(that name is mediocre, im sure we can come up with something better) work when derivingPatch
?
I guess we would need something a bit more sophisticated when we still want to be able to derivePatch
for the same struct which represents theTable
Regardless, I'd definetely appraciate if you would open an issue for this, possibly outlining possible approaches like this
Sorry for not having a more minimal example (I might post one soonish) but this should be fairly straightforward if not minimal.
This code gives : wildcard overrides are only allowed with an explicit record type, e.g. query_as!() and its variants
#[derive(Debug, ormx::Table)]
#[ormx(
table = "Account",
id = id,
insertable,
deletable
)]
pub struct Account {
#[ormx(default, get_many=get_many_by_id)]
id: i32,
#[ormx(get_one, get_many=get_many_by_email, set)]
email: String,
#[ormx(set)]
password_hash: String,
#[ormx(default)]
creation_time: OffsetDateTime,
#[ormx(default, custom_type, set)] //<-- removing the default attribute fixes the compile error
account_type: AccountType,
#[ormx(default, set)]
suspended: bool,
}
Here's the custom type in question :
#[derive(
PartialEq, Debug, Copy, Clone, sqlx::Type, Serialize, Deserialize, AsRefStr, IntoStaticStr,
)]
#[sqlx(type_name = "AccountType")]
pub enum AccountType {
Temporary,
Guest,
Admin,
}
And here's the database schema I'm compiling against :
CREATE TABLE Account
(
id SERIAL UNIQUE,
email TEXT PRIMARY KEY,
password_hash TEXT NOT NULL,
creation_time TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
account_type AccountType NOT NULL DEFAULT 'Temporary',
suspended BOOLEAN NOT NULL DEFAULT false
);
Would it be possible to add a conditional_query! macro? I use query! from sqlx much more than query_as! so I'd love to be able to replicate some of the possibilities with filtering and pattern matching that you have enabled, but with the other macro.
Why not support sqlite
As far as I know, it is generally considered best practice to enforce that the ID column will always be generated. The GENERATED ALWAYS
modifier allows this. Additionally, the AS IDENTITY
modifier creates the numeric sequence.
The documentation for deriving Table states that:
ormx will generate a helper struct for inserting rows into the database when using
#[ormx(insertable)]
.
This struct will contain all fields of the struct, except
- the ID
- fields annotated with
#[ormx(default)]
since the value of these fields will be generated by the database.
However, the implementation of the derive macro for the Insertable trait does not follow this:
ormx/ormx-macros/src/table/mod.rs
Lines 48 to 50 in bc65c51
I believe insertable_fields
should also exclude the ID, or maybe the ID should be marked as having a default value by setting the default
field to true
.
Hi!
Why I try to use ormx with my model:
#[derive(Debug, Serialize, Deserialize, FromRow, Encode, Eq, PartialEq, Clone, ormx::Table)]
#[ormx(table = "users.list", id = id, insertable)]
pub struct User {
#[serde(default)]
pub id: i32,
pub login: Option<String>,
// #[serde(skip)]
pub password: Option<String>,
pub name: Option<String>,
pub subname: Option<String>,
pub phone: Option<String>,
pub desc: Option<String>,
pub access_card: Option<i32>,
pub owner_id: Option<i32>,
pub register_date: Option<chrono::NaiveDateTime>,
}
I got an error:
error: error returned from database: syntax error at or near "desc"
I think the problem is that you don't escape columns names and desc is a keyword in PostgreSQL :/.
I think this should be easy to fix?
I'm interested why ormx chose to return boxed future and stream instead of impl Future
and impl Stream
respectively?
Firstly, thanks for a useful crate.
I have encountered an issue that seems to affect Table::all / all_paginated/ stream-all / stream_all_paginated / get_many. There appears to be no way currently to specify the order of the results and the order varies after updates or inserts, this makes the paginated functions not too useful. If I am mistaken could the documentation be changed to show how.
I am using postgres but as SQL does not guarantee an ordering for a select, this would apply to all databases. Sql standard states "If an is not specified, then the ordering of the rows of Q is implementation-dependent."
Would there be a way to specify at the Table level an "order by"
#[ormx(table = "...",order="id asc")]
or for several
#[ormx(table = "...",order="firstname asc, lastname asc")]
#[ormx(get_many,order="firstname asc, lastname asc"))]:
or if not then could you add an example to do order by, offset and limit using the conditional_query_as macro, and maybe clarify in the methods mentioned that the order is not guaranteed.
Thanks
thanks
I am trying to update sqlx to 0.7, but Insert trait let mut tx = db.begin().await?;
db: impl Executor has no begin method on sqlx 0.7
db: &mut <Db as Database>::Connection,
row: impl Insert<Table = Self>,
) -> BoxFuture<Result<Self>> {
- row.insert(db)
+ row.insert(&mut *db)
}
/// Insert a row into the database, returning the inserted row.
- fn insert<'a, 'c: 'a>(
+ fn insert(
self,
- db: impl Executor<'c, Database = Db> + 'a,
- ) -> BoxFuture<'a, Result<Self::Table>>;
+ db: &mut impl sqlx::Connection<Database = Db, Options=sqlx::mysql::MySqlConnectOptions>,
+ ) -> BoxFuture<Result<Self::Table>>;
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.