-
Notifications
You must be signed in to change notification settings - Fork 1.4k
query_as! macros do not use FromRow #514
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
We unfortunately have no way to do this right now while keeping the guarantee that output columns and types match the field names and types in the struct. We could possibly do some type-level magic with I think with the |
|
Ah, thanks. |
Could we at least document this currently for now? As It was not clear for me. |
This is already stated in the documentation: https://github.com/launchbadge/sqlx/blob/master/src/macros.rs#L379 This is also stated in the documentation for If that isn't clear enough then we'd love suggestions for better phrasing. |
The beta version is okay as it is, but I think it would be better if it directly mentions the |
The documentation also goes on to explain, pretty clearly I think, how the macro maps rows to the struct. However, "no trait implementations are required" can be misleading because
|
Can you pin the link to a commit? Otherwise the line number gets outdated. It would be nice to have a note about this at the top of https://docs.rs/sqlx/0.5.5/sqlx/trait.FromRow.html . That's where I started looking first when using |
I'm sure adding more docs would be appreciated 😉 |
Just run into this too - Also: Rust 1.57 has stabilized |
Has any work been done on this? If not I’d be willing to try and help contribute this feature. |
im also waiting on this |
So, to use nested fields we need EDIT: Well, I just tried to use FromRow anyway, only to realize |
that deserves its own issue and there probably already is one |
@rsalmei I think what you are looking for is something like the slqx::query_as("SELECT foo FROM bar WHERE name = ? AND age = ?")
.bind("Harrison Ford")
.bind(80); |
It seems like the |
It can, but I'm not really happy about how the compiler currently handles const panics: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=33e7700ac709e6581dcf478fb3c3b3b4 I proposed a format that would be more useful to us during the feature's development, but it was brushed off: rust-lang/rust#51999 (comment) We also can't use |
There's also the issue of formatting the error messages. We'd like to be able to output something like:
However, There's been some relevant groundwork laid, e.g.: rust-lang/rust#78356 But I cannot find evidence of any movement for allowing non-trivial format args in const The It's basically the same approach as the I suppose knowing that the former exists and is actively maintained is enough, but it is still rather a dumb reason to reach for |
I have managed to modify pub const unsafe fn union_transmute<From, To>(from: From) -> To
where
From: Copy,
To: Copy,
{
union Transmute<From: Copy, To: Copy> {
from: From,
to: To,
}
Transmute { from }.to
}
pub const unsafe fn concat<First, Second, Out>(a: &[u8], b: &[u8]) -> Out
where
First: Copy,
Second: Copy,
Out: Copy,
{
#[derive(Copy, Clone)]
struct Both<A, B>(A, B);
let arr: Both<First, Second> = Both(
*union_transmute::<_, &First>(a),
*union_transmute::<_, &Second>(b),
);
union_transmute(arr)
}
#[macro_export]
macro_rules! const_concat {
($a:expr, $b:expr) => {{
let bytes: &'static [u8] = unsafe {
&$crate::concat::<
[u8; $a.len()],
[u8; $b.len()],
[u8; $a.len() + $b.len()],
>($a.as_bytes(), $b.as_bytes())
};
unsafe { $crate::union_transmute::<_, &'static str>(bytes) }
}};
($a:expr, $($rest:expr),*) => {{
const TAIL: &str = const_concat!($($rest),*);
const_concat!($a, TAIL)
}};
($a:expr, $($rest:expr),*,) => {
const_concat!($a, $($rest),*);
};
}
#[cfg(test)]
mod tests {
#[test]
fn top_level_constants() {
const HELLO: &str = "Hello";
const COMMA: &str = ", ";
const WORLD: &str = "world";
const GREETING2: &str = const_concat!(HELLO, WORLD);
const GREETING3: &str = const_concat!(HELLO, COMMA, WORLD);
const GREETING4: &str = const_concat!(HELLO, COMMA, WORLD, "!");
const GREETING6: &str = const_concat!(HELLO, COMMA, WORLD, "!", "1", "2");
// const GREETING_TRAILING_COMMA: &str = const_concat!(HELLO, COMMA, WORLD, "!",);
assert_eq!(GREETING2, "Helloworld");
assert_eq!(GREETING3, "Hello, world");
assert_eq!(GREETING4, "Hello, world!");
assert_eq!(GREETING6, "Hello, world!12");
// assert_eq!(GREETING_TRAILING_COMMA, "Hello, world!");
}
} But it fails on assertion And it does not matter if you use Without macros (expanded) version: fn main() {
const HELLO: &str = "Hello";
const COMMA: &str = ", ";
const WORLD: &str = "world";
const TAIL: &'static str = {
const TAIL: &'static str = {
let bytes: &'static [u8] = unsafe {
&crate::concat::<[u8; WORLD.len()], [u8; "!".len()], [u8; WORLD.len() + "!".len()]>(
WORLD.as_bytes(),
"!".as_bytes(),
)
};
unsafe { crate::union_transmute::<_, &'static str>(bytes) }
};
{
let bytes: &'static [u8] = unsafe {
&crate::concat::<[u8; COMMA.len()], [u8; TAIL.len()], [u8; COMMA.len() + TAIL.len()]>(
COMMA.as_bytes(),
TAIL.as_bytes(),
)
};
unsafe { crate::union_transmute::<_, &'static str>(bytes) }
}
};
let bytes: [u8; 13] = unsafe {
crate::concat::<[u8; HELLO.len()], [u8; TAIL.len()], [u8; HELLO.len() + TAIL.len()]>(
HELLO.as_bytes(),
TAIL.as_bytes(),
)
};
println!("{}", String::from_utf8(bytes.to_vec()).unwrap()); // ", world!Hello"
} |
Looks like
@abonander As far as I understood, you need to |
I've just wrote my own implementation. Is it safe enough? |
Please, I am confused by this @rsalmei previous comment. Talking about "nested structs" - I have seen examples of |
What's blocking this one? |
@domenkozar the answer is, like pretty much always, "I haven't had time to work on it". I'm fairly certain it's possible now with more stable functionality in Please do not spam this issue for updates. If there was movement, there'd be a draft PR. |
@abonander thanks a lot for all your work! I was wondering why there's no obvious way to sponsor features/bugfixes development? Something worthwhile exploring, I might get a budget to sponsor this! |
We were previously discussing a paid offering but those plans have fallen by the wayside as other things got in the way, and we didn't see nearly as much interest in it from the community as we were expecting. From what I'm told, we got basically zero serious inquiries about it. I'm actually technically not an employee of Launchbadge anymore, but of a spun-off company. We still have a very good working relationship, however, and I essentially have been given creative control here. My current employer actually gives me a little bit of dedicated time to work on SQLx, but I still have my primary duties as a software engineer and a team leader to balance with that. We've talked about setting up Github Sponsors but it would not be through either company, it'd be paying me directly. The problem is, I would either have to eat into my personal time to work on SQLx (which I do a little bit anyway, but as a hobby, not a second job), or make an agreement with my employer to reduce my obligations (and likely my pay, accordingly) to make room for it, but that wouldn't really work at this time as we're pushing towards a product launch. If, for whatever reason, I were to leave my current position, I do intend to make a go of it working on SQLx full time, supported by sponsors. It's just not in the cards right now. |
i'd be interested in working on sqlx in the future, but onboarding such a large project is always time consuming and overwhelming at first, maybe if theres a contribution guide that explains each part of the internal code it'd be easier for new contributors to join |
Hi, just wondering; does this mean when using I'm trying to explore the practical differences between the macros and functions, I can see the macros are perhaps more comprehensive as they also require a connection to the db to check types. For the sake of code organization I would like to be able to store queries separate in sql files and simply call them from rust code with similar functionality as the regular Thanks for sqlx, it's very straightforward and non "invasive" and fills a big gap I had, I don't also don't mean for this comment to seam like endless requests, cause I'm also quite limited in my rust ability so couldn't work towards any of this, it's more of a request for information about the rationale between the macros and functions. Thanks |
|
Thanks for the very quick response. I had asked cause I got here trying to look into this. I was playing around switching my But I am using derive Would that difference (macros not using FromRow but functions do) explain that? Or perhaps I am doing some else wrong entirely. Thanks |
The macros (currently) have no interaction with |
Alright thank you, so as I understand |
instead the
query_as!
macro's directly build the target struct, while it might be nice not to have to deriveFromRow
for the struct, this also means that you can't customize the behaviour with a customFromRow
implementation.The text was updated successfully, but these errors were encountered: