-
-
Notifications
You must be signed in to change notification settings - Fork 23
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
Async query execution in spawned task #276
Comments
Hi @lanklaas , thanks for giving the async API a spin. It comes with a bunch of caveats, but in this case it's just something in the error message you have seemed to miss.
So, your closure is not
This means in a multithreaded async runtime another thread might pick up the task. There is little I can think of right now, to make this more convinient (at least within a zero cost abstraction), because ODBC has this annoying property of maintaining mutable state for error messages. However, I feel for your code might benefit from allocating statement handles explicitly. Check out This might even get rid of the unsafe code completly. Would need to try later to know for sure though. Cheers, Markus |
Thanks for the quick response. I tried to put it in a Mutex as well as a Arc, but I still got the issue. Should the mutex work here or will it never work across an await? Updated code: use lazy_static::lazy_static;
use odbc_api::Environment;
use std::{
sync::{Arc, Mutex},
thread,
time::Duration,
};
lazy_static! {
static ref ENV: Environment = unsafe { Environment::new().unwrap() };
}
#[tokio::main]
async fn main() {
const MSSQL: &str = "Driver={ODBC Driver 17 for SQL Server};\
Server=localhost;\
UID=SA;\
PWD=My@Test@Password1;\
";
let conn = ENV.connect_with_connection_string("MSSQL").unwrap();
let conn = Arc::new(Mutex::new(unsafe { conn.promote_to_send() }));
let conn = Arc::clone(&conn);
let handle = tokio::task::spawn(async move {
let conn = Arc::clone(&conn);
let lock = conn.lock().unwrap();
let exec = lock.execute_polling("SELECT 1", (), || {
tokio::time::sleep(Duration::from_secs(1))
});
if let Some(cursor) = exec.await.unwrap() {
// dbg!(cursor);
}
// if let Some(cursor) = conn.execute("SELECT 1", ()).unwrap() {
// // dbg!(cursor);
// }
});
handle.await;
} The full error:
|
May I ask why you spawn a task with |
It is the closest I could get the example to the actual code. I have a lib crate that compiles fine with the async API, but when I use it in my bin crate which spawns tasks for multiple kafka listeners I get this issue |
Sorry for the confusion with the |
Ok thanks for the help! Will use sync for now. I will leave the ticket open, but you can close it if you like |
Thank you too. Especially for the minimal reproducing example. I'll leave it open until it's either working or I understand precisly why it can not. |
A little update. This works today using I am also currently evaluating the safety of making statements Best, Markus |
Hello,
I am trying to use the execute polling method on a connection, but the compiler keeps saying that the connection is not send, even though I promoted it to send.
This is the error
Some testing code that produces it. I used the example for
promote_to_send
and made it async.Cargo.toml
Rust info:
Is there a way around this or should I go back to the sync API?
The text was updated successfully, but these errors were encountered: