According to the Tiberius documentation, using the SQLConnection::simple_query() function is as simple as:

extern crate futures;
extern crate futures_state_stream;
extern crate tokio;
extern crate tiberius;
use futures::Future;
use futures_state_stream::StateStream;
use tokio::executor::current_thread;
use tiberius::SqlConnection;

fn main() {

   // 1: for windows we demonstrate the hardcoded variant
   // which is equivalent to:
   //     let conn_str = "server=tcp:localhost,1433;integratedSecurity=true;";
   //     let future = SqlConnection::connect(conn_str).and_then(|conn| {
   // and for linux we use the connection string from an environment variable
   let conn_str = if cfg!(windows) {
       "server=tcp:localhost,1433;integratedSecurity=true;".to_owned()
   } else {
       ::std::env::var("TIBERIUS_TEST_CONNECTION_STRING").unwrap()
   };

   let future = SqlConnection::connect(conn_str.as_str())
       .and_then(|conn| {
           conn.simple_query("SELECT 1+2").for_each(|row| {
               let val: i32 = row.get(0);
               assert_eq!(val, 3i32);
               Ok(())
           })
       })
       .and_then(|conn| conn.simple_exec("create table #Temp(gg int);"))
       .and_then(|(_, conn)| conn.simple_exec("UPDATE #Temp SET gg=1 WHERE gg=1"));

   current_thread::block_on_all(future).unwrap();
}

However, I am using tiberius crate verson 0.3.2 as follows, and I get a compile-time error. I can't tell what I'm doing wrong because the QueryResult type doesn't indicate what kind of wrapper I need to wrap the value in (there's no manually written documentation or examples in the QueryResult docs, only auto-generated API docs, which are quite cryptic for a new Rust programmer! :( )

I'm used to processing StdResults and Options with things like Ok() and Err() and Some(), and I feel like I need to do something like Ok(rslt) on line 7 below, but that gives me a compile-time error too.

  • Question 1: Is the documentation correct? If my code doesn't compile, I'd think the documentation code wouldn't either... unless I'm using the wrong version of Rust (using stable) or unless the Tiberius docs are only correct for some older version of Tiberius.
  • Question 2: How do I fix the compile-time error and do something equivalent to the doc example? I just want to run one trivial query and return the results processed into a string.
fn get_users() -> String {
    let conn_str : &str = &::std::env::var("SQLCONN").expect("Could not obtain SQLCONN");
    let mut output = String::new();
    let first : bool = true;
    let future = SqlConnection::connect(conn_str)
    .and_then(|conn| {
        if let rslt = conn.simple_query("SELECT \"A\", \"B\"") {
            rslt.for_each(|row| {
                let account : &str = row.get(0);
                let charName : &str = row.get(1);
                if first == false {
                    output.push_str("\r\n");
                }
                output.push_str(account);
                output.push_str(" is logged in as ");
                output.push_str(charName);
                first = false;
                Ok(())
            })
        }
    });
    block_on_all(future).unwrap();
    output
}

Error output:

error[E0599]: no method named `for_each` found for type `tiberius::stmt::QueryResult<tiberius::query::ResultSetStream<std::boxed::Box<dyn tiberius::BoxableIo>, tiberius::query::QueryStream<std::boxed::Box<dyn tiberius::BoxableIo>>>>` in the current scope
   --> src\main.rs:104:18
    |
104 |             rslt.for_each(|row| {
    |                  ^^^^^^^^
    |
    = note: the method `for_each` exists but the following trait bounds were not satisfied:
            `&mut tiberius::stmt::QueryResult<tiberius::query::ResultSetStream<std::boxed::Box<dyn tiberius::BoxableIo>, tiberius::query::QueryStream<std::boxed::Box<dyn tiberius::BoxableIo>>>> : futures_state_stream::StateStream`
            `&mut tiberius::stmt::QueryResult<tiberius::query::ResultSetStream<std::boxed::Box<dyn tiberius::BoxableIo>, tiberius::query::QueryStream<std::boxed::Box<dyn tiberius::BoxableIo>>>> : std::iter::Iterator`
    = help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope, perhaps add a `use` for it:
    |
2   | use futures_state_stream::StateStream;
    |

1 Answers

0
allquixotic On

Looks like there was a breaking change to futures_state_stream and I was using a version too new for this package, which caused the breakage.

I had to downgrade futures_state_stream version to 0.1.0 until this issue is resolved.