Repository: blackbeam/rust-mysql-simple (language: rust)

Issue:
Example code does not work for me
Im just trying to run the simple example to connect to a database but im getting an error on the line trying to create a new Pool. Here is my code 

```
use mysql::*;
use mysql::prelude::*;

fn main() {
    println!("Hello, world!");
    let url = "db-string";
    let pool = Pool::new(url)?;
}
```

Im getting an error on the last line. it says: 

```
error[E0277]: the trait bound `Opts: From<&str>` is not satisfied
   --> src/main.rs:7:26
    |
7   |     let pool = Pool::new(url)?;
    |                --------- ^^^ the trait `From<&str>` is not implemented for `Opts`
    |                |
    |                required by a bound introduced by this call

```

Im pretty new to rust so can someone help me with this?


Discussion / hints:
@conormdowney, hi.
Sorry, but looks like the example code wasn't properly updated.
Following code should work:

```rust
use mysql::*;
use mysql::prelude::*;

fn main() {
    println!("Hello, world!");
    let opts = Opts::from_url("db-string")?;
    let pool = Pool::new(opts)?;
}
```

Thanks for the update. Im getting a different error now with the code you gave me: 

```
fn main() {
5  | |     println!("Hello, world!");
6  | |     let opts = Opts::from_url("db-string")?;
7  | |     let pool = Pool::new(opts)?;
   | |                               ^ cannot use the `?` operator in a function that returns `()`
```

If i unwrap() instead of the use the ? it works though. just in case any other newbie runs into this issue.

This one already answered [here](https://github.com/blackbeam/rust-mysql-simple/issues/296#issuecomment-951739645).
Thats cool. thanks. I am curious though, and i realise this isnt really the place for this but hoping you wont mind, for Pool::new, its return type is Result<Pool>. Why not Result<Pool, Error>. If something goes wrong there it still expects a Pool back, correct? 
This result is just a type alias to `std::result::Result` defined here: https://github.com/blackbeam/rust-mysql-simple/blob/6d856627425a19a854f13324bb6cdc93f7eb857e/src/error/mod.rs#L350

It's a usual practise for libraries and modules to define it's own type aliases to Result (eg std::Io::Result, std::fmt::Result)
okay. cool. Im still wrapping my head around error handling in Rust. If I was to do a match on the result (not necessary I know) then I would need the Error to return the appropriate type. This issue is fixed though so ill close it. Thanks

Fix patch:
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 92a91c3..e344988 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -230,6 +230,10 @@ jobs:
     strategy:
       maxParallel: 10
       matrix:
+        v108:
+          DB_VERSION: "10.8"
+        v107:
+          DB_VERSION: "10.7"
         v106:
           DB_VERSION: "10.6"
         v105:
diff --git a/src/conn/mod.rs b/src/conn/mod.rs
index 3f4fef7..d6b6221 100644
--- a/src/conn/mod.rs
+++ b/src/conn/mod.rs
@@ -175,8 +175,7 @@ struct ConnInner {
 }
 
 impl ConnInner {
-    fn empty<T: Into<Opts>>(opts: T) -> Self {
-        let opts = opts.into();
+    fn empty(opts: Opts) -> Self {
         ConnInner {
             stmt_cache: StmtCache::new(opts.get_stmt_cache_size()),
             opts,
@@ -316,7 +315,12 @@ impl Conn {
     }
 
     /// Creates new `Conn`.
-    pub fn new<T: Into<Opts>>(opts: T) -> Result<Conn> {
+    pub fn new<T, E>(opts: T) -> Result<Conn>
+    where
+        Opts: TryFrom<T, Error = E>,
+        crate::Error: From<E>,
+    {
+        let opts = Opts::try_from(opts)?;
         let mut conn = Conn(Box::new(ConnInner::empty(opts)));
         conn.connect_stream()?;
         conn.connect()?;
diff --git a/src/conn/opts/mod.rs b/src/conn/opts/mod.rs
index d43d81a..c041605 100644
--- a/src/conn/opts/mod.rs
+++ b/src/conn/opts/mod.rs
@@ -255,6 +255,14 @@ impl Default for InnerOpts {
     }
 }
 
+impl TryFrom<&'_ str> for Opts {
+    type Error = UrlError;
+
+    fn try_from(url: &'_ str) -> Result<Self, Self::Error> {
+        Opts::from_url(url)
+    }
+}
+
 /// Mysql connection options.
 ///
 /// Build one with [`OptsBuilder`](struct.OptsBuilder.html).
@@ -491,7 +499,7 @@ impl Opts {
 /// let connection_url = "mysql://root:password@localhost:3307/mysql?prefer_socket=false";
 /// let pool = my::Pool::new(connection_url).unwrap();
 /// ```
-#[derive(Debug, PartialEq)]
+#[derive(Debug, Clone, PartialEq)]
 pub struct OptsBuilder {
     opts: Opts,
 }
@@ -1019,7 +1027,17 @@ mod test {
     use mysql_common::proto::codec::Compression;
     use std::time::Duration;
 
-    use super::{InnerOpts, Opts};
+    use super::{InnerOpts, Opts, OptsBuilder};
+
+    #[allow(dead_code)]
+    fn assert_conn_from_url_opts_optsbuilder(url: &str, opts: Opts, opts_builder: OptsBuilder) {
+        crate::Conn::new(url).unwrap();
+        crate::Conn::new(opts.clone()).unwrap();
+        crate::Conn::new(opts_builder.clone()).unwrap();
+        crate::Pool::new(url).unwrap();
+        crate::Pool::new(opts).unwrap();
+        crate::Pool::new(opts_builder).unwrap();
+    }
 
     #[test]
     fn should_report_empty_url_database_as_none() {
diff --git a/src/conn/pool.rs b/src/conn/pool.rs
index 37886d9..2115945 100644
--- a/src/conn/pool.rs
+++ b/src/conn/pool.rs
@@ -180,13 +180,21 @@ impl Pool {
     }
 
     /// Creates new pool with `min = 10` and `max = 100`.
-    pub fn new<T: Into<Opts>>(opts: T) -> Result<Pool> {
+    pub fn new<T, E>(opts: T) -> Result<Pool>
+    where
+        Opts: TryFrom<T, Error = E>,
+        crate::Error: From<E>,
+    {
         Pool::new_manual(10, 100, opts)
     }
 
     /// Same as `new` but you can set `min` and `max`.
-    pub fn new_manual<T: Into<Opts>>(min: usize, max: usize, opts: T) -> Result<Pool> {
-        let pool = InnerPool::new(min, max, opts.into())?;
+    pub fn new_manual<T, E>(min: usize, max: usize, opts: T) -> Result<Pool>
+    where
+        Opts: TryFrom<T, Error = E>,
+        crate::Error: From<E>,
+    {
+        let pool = InnerPool::new(min, max, opts.try_into()?)?;
         Ok(Pool {
             arced_pool: Arc::new(ArcedPool {
                 inner: (Mutex::new(pool), Condvar::new()),
diff --git a/src/lib.rs b/src/lib.rs
index 20901ad..55a97b8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -53,6 +53,7 @@
 //! }
 //!
 //! let url = "mysql://root:password@localhost:3307/db_name";
+//! # Opts::try_from(url)?;
 //! # let url = get_opts();
 //!
 //! let pool = Pool::new(url)?;


Test patch: